本系列將從如下專題去總結:app
1. JS基礎知識深刻總結
2. 對象高級
3. 函數高級
4. 事件對象與事件機制ide
暫時會對以上四個專題去總結,如今開始Part2:對象高級。下圖是我這篇的大綱。 函數
方式一:Object構造函數模式post
// 先建立空Object對象
var p = new Object()
p = {} //此時內部數據是不肯定的
// 再動態添加屬性/方法
p.name = 'Tom'
p.age = 12
p.setName = function (name) {
this.name = name
}
//測試
console.log(p.name, p.age) //Tom 12
p.setName('Bob')
console.log(p.name, p.age) //Bob 12
複製代碼
方式二:對象字面量模式學習
{}
建立對象, 同時指定屬性/方法var p = {
name: 'Tom',
age: 12,
setName: function (name) {
this.name = name
}
}
//測試
console.log(p.name, p.age) //Tom 12
p.setName('JACK')
console.log(p.name, p.age) //JACK 12
var p2 = { //若是建立多個對象代碼很重複
name: 'Bob',
age: 13,
setName: function (name) {
this.name = name
}
}
複製代碼
方式三:工廠模式(相對使用不多)測試
function createPerson(name, age) { //返回一個對象的函數通常稱爲===>工廠函數
var obj = {
name: name,
age: age,
setName: function (name) {
this.name = name
}
}
return obj
}
// 建立2我的
var p1 = createPerson('Tom', 12)
var p2 = createPerson('Bob', 13)
// p1和p2是Object類型
function createStudent(name, price) {
var obj = {
name: name,
price: price
}
return obj
}
var s = createStudent('張三', 12000)
// s也是Object
複製代碼
方式四:自定義構造函數模式flex
//定義類型,Person類型
function Person(name, age) {
this.name = name
this.age = age
this.setName = function (name) {
this.name = name
}
}
var p1 = new Person('Tom', 12)
p1.setName('Jack')
console.log(p1.name, p1.age) //Jack 12
console.log(p1 instanceof Person) //true
function Student (name, price) {
this.name = name
this.price = price
}
var s = new Student('Bob', 13000)
console.log(s instanceof Student) //true
var p2 = new Person('JACK', 23)
console.log(p1, p2) //都返回Person類型對象
複製代碼
方式五: 構造函數+原型的組合模式ui
function Person(name, age) { //在構造函數中只初始化屬性
this.name = name
this.age = age
}
//方法放在原型對象裏,就不會重複了。減小內存壓力。
Person.prototype.setName = function (name) {
this.name = name
}
var p1 = new Person('Tom', 23)
var p2 = new Person('Jack', 24)
console.log(p1, p2) //都返回一個Person類型對象
複製代碼
大體的程序步驟思想:this
function Parent(){}//父 構造函數
Parent.prototype.test = function(){};//在父的原型對象上添加test方法
function Child(){}// 子 構造函數
Child.prototype = new Parent(); // 子類型的原型指向父類型實例
Child.prototype.constructor = Child;//最好也把constructor也從新置給Child構造函數
var child = new Child(); //有test()
複製代碼
//父類型
function Supper() {
this.supProp = 'Supper property'
}
Supper.prototype.showSupperProp = function () {
console.log(this.supProp)
}
//子類型
function Sub() {
this.subProp = 'Sub property'
}
// 子類型的原型爲父類型的一個實例對象
Sub.prototype = new Supper()
// 讓子類型的原型的constructor指向子類型(構造函數)
Sub.prototype.constructor = Sub
Sub.prototype.showSubProp = function () {
console.log(this.subProp)
}
var sub = new Sub()
sub.showSupperProp() //Supper property
sub.showSubProp() //Sub property
console.log(sub) // 返回Sub類型對象
複製代碼
案例圖解: spa
給個案例分析:
function Person(name, age) {
this.name = name
this.age = age
}
function Student(name, age, price) {
//爲了得到父類型的Person的屬性繼承
Person.call(this, name, age) // 借調。至關於: this.Person(name, age)
/*this.name = name this.age = age 以上這兩行代碼就可沒必要寫了 */
this.price = price
}
var s = new Student('Tom', 20, 14000)
console.log(s.name, s.age, s.price) //Tom 20 14000
複製代碼
給個案例分析:
//相似於父函數
function Person(name, age) {
this.name = name
this.age = age
}
Person.prototype.setName = function (name) {
this.name = name
}
//相似於子函數
function Student(name, age, price) {
Person.call(this, name, age) // 爲了獲得屬性(屬性的繼承)
this.price = price
}
Student.prototype = new Person() // 爲了能看到父類型的方法(方法的繼承--經過原型鏈)
Student.prototype.constructor = Student //修正constructor屬性
Student.prototype.setPrice = function (price) {
this.price = price
}
var s = new Student('Tom', 24, 15000)
s.setName('Bob');
s.setPrice(16000);
console.log(s.name, s.age, s.price) //Bob 24 16000
複製代碼
在ES6中引入了class
關鍵字,但更多的是一種語法糖,本質上仍是寄生組合繼承的繼承方式。是一種相對完美的繼承方式。
寄生組合繼承的核心總結如下幾點:(邊看圖邊看文字理解)
1.子類構造函數的 __proto__
指向父類構造器,繼承父類的靜態方法
2.子類構造函數的 prototype
的 __proto__
指向父類構造器的 prototype
,繼承父類的方法。
[ 1和2這兩點也就是下圖橙色標記的兩條線。]
3.子類構造函數繼承了父類構造函數裏的屬性。使用 super
調用的( ES5則用 call
或者 apply
調用傳參)。
class Animal {
constructor(name) {
this.speed = 0;
this.name = name;
}
run(speed) {
this.speed += speed;
alert(`${this.name} runs with speed ${this.speed}.`);
}
stop() {
this.speed = 0;
alert(`${this.name} stopped.`);
}
}
// Inherit from Animal
class Rabbit extends Animal {
hide() {
alert(`${this.name} hides!`);
}
}
let rabbit = new Rabbit("White Rabbit");
rabbit.run(5); // White Rabbit runs with speed 5.
rabbit.hide(); // White Rabbit hides!
複製代碼
如你所見,如你所想,extend
關鍵字其實是在 Rabbit.prototype
添加[[proto]]
,引用到 Animal.prototype
。
rabbit
既能夠訪問它本身的方法,也能夠訪問
Animal
的方法。
看咱們嚐嚐寫的一個例子:
function Person() {
this.name = name
this.age = age
}
var person = new Person()
複製代碼
事實上,new一個對象作了什麼呢?完整執行的代碼:
function Person() {
var this = {
__proto__: Person.prototype
}
this.name = name
this.age = age
return this
}
var person = new Person()
複製代碼
故new一個對象作了如下幾步:
__proto__
, 值爲構造函數對象的prototype
屬性值 this.__proto__ = Fn.prototype
return this
,返回新對象Object
(包含Function
Array
Date
RegExg
Error
),則默認隱式 return this
( this
指代剛new出來的對象實例)。通常狀況下,構造函數不返回值,可是用戶能夠選擇主動返回一個對象,這個對象就會覆蓋默認返回的 this
實例)。Number
String
Boolean
等),這個時候仍是返回默認的this
!只有返回對象類型,纔會覆蓋原先的this
!
此文檔爲呂涯原創,可任意轉載,但請保留原連接,標明出處。 文章只在CSDN和掘金第一時間發佈: CSDN主頁:https://blog.csdn.net/LY_code 掘金主頁:https://juejin.im/user/5b220d93e51d4558e03cb948 如有錯誤,及時提出,一塊兒學習,共同進步。謝謝。 😝😝😝