網(wǎng)易云播放器做網(wǎng)站播放編程培訓班學費一般多少錢
1、簡介
類Class 可以通過extends
關(guān)鍵字實現(xiàn)繼承,讓子類繼承父類的屬性和方法。extends 的寫法比 ES5 的原型鏈繼承,要清晰和方便很多。
class Foo {constructor(x, y) {this.x = x;this.y = y;console.log('父類構(gòu)造函數(shù)')}toString() {return '(' + this.x + ', ' + this.y + ')';}
}class Baroo extends Foo {constructor(x, y, color) {this.color = color; // ReferenceError super(x, y)之后才能使用子類thissuper(x, y); // 調(diào)用父類的constructor(x, y) 目的是新建子類實例this.color = color;console.log(x,y,color)console.log('子類構(gòu)造函數(shù)')}toString() {return this.color + ' ' + super.toString(); // 調(diào)用父類的toString()}
}let baroo = new Baroo(1,2,'#ffffff') // 1,2,'#ffffff'
console.log(baroo) //Baroo {x: 1, y: 2, color: '#ffffff'}
console.log(baroo.toString()) // #ffffff (1, 2)
上面示例中,constructor()
方法和toString()
方法內(nèi)部,都出現(xiàn)了super
關(guān)鍵字。super
在這里表示父類的構(gòu)造函數(shù),用來新建一個父類的實例對象
ES6 規(guī)定,子類必須在constructor()
方法中調(diào)用super()
,否則就會報錯。這是因為子類自己的this
對象,必須先通過父類的構(gòu)造函數(shù)完成塑造,得到與父類同樣的實例屬性和方法,然后再對其進行加工,添加子類自己的實例屬性和方法。如果不調(diào)用super()
方法,子類就得不到自己的this
對象。
注意,這意味著新建子類實例時,父類的構(gòu)造函數(shù)必定會先運行一次。
上面示例中,子類 Bar 新建實例時,會輸出 "父類構(gòu)造函數(shù)","子類構(gòu)造函數(shù)"。原因就是子類構(gòu)造函數(shù)調(diào)用super()
時,會執(zhí)行一次父類構(gòu)造函數(shù)(并在調(diào)用super()后才能使用子類的this,否則會報錯)
// 如果子類沒有定義constructor()方法,這個方法會默認添加,并且里面會調(diào)用super()。
// 也就是說,不管有沒有顯式定義,任何一個子類都有constructor()方法。class ColorPoint extends Point {}// 等同于
class ColorPoint extends Point {constructor(...args) {super(...args);}
}
2、super關(guān)鍵字
super
這個關(guān)鍵字,既可以當作函數(shù)使用,也可以當作對象使用。在這兩種情況下,它的用法完全不同。
第一種情況,super
作為函數(shù)調(diào)用時,代表父類的構(gòu)造函數(shù)。ES6 要求,子類的構(gòu)造函數(shù)必須執(zhí)行一次super()
函數(shù)。
class Foo {}class Boo extends Foo {constructor() {super();}
}//子類B的構(gòu)造函數(shù)之中的super(),代表調(diào)用父類的構(gòu)造函數(shù)。這是必須的,否則報錯
注意,這里的super
雖然代表了父類的構(gòu)造函數(shù),但是因為返回的是子類的this
(即子類的實例對象),所以super
內(nèi)部的this
代表子類的實例,而不是父類的實例,這里的super()
相當于A.prototype.constructor.call(this)
(在子類的this
上運行父類的構(gòu)造函數(shù))。
class A {constructor() {console.log(new.target.name);}
}
class B extends A {constructor() {super();}
}
new A() // A
new B() // B
上面示例中,new.target
指向當前正在執(zhí)行的函數(shù)。可以看到,在super()
執(zhí)行時(new B()
),它指向的是子類B
的構(gòu)造函數(shù),而不是父類A
的構(gòu)造函數(shù)。
ES6 規(guī)定,在子類普通方法中通過super
調(diào)用父類的方法時,方法內(nèi)部的this
指向當前的子類實例,也就是說,super()
內(nèi)部的this
指向的是B。
3、類的prototype屬性和__proto__屬性
在之前ES5實現(xiàn)中,每個對象都有__proo__屬性,指向?qū)臉?gòu)造函數(shù)的prototype屬性。
ES6中類Class 作為構(gòu)造函數(shù)的語法糖,同時有prototype
屬性和__proto__
屬性,因此同時存在兩條繼承鏈。
(1)子類的
__proto__
屬性,表示構(gòu)造函數(shù)的繼承,總是指向父類。(2)子類
prototype
屬性的__proto__
屬性,表示方法的繼承,總是指向父類的prototype
屬性。
class A {}class B extends A {
}B.__proto__ === A // true
B.prototype.__proto__ === A.prototype // true