在ES6中使用class實(shí)現(xiàn)繼承们拙,子類必須在constructor方法中調(diào)用super方法曲稼,否則新建實(shí)例時(shí)會(huì)報(bào)錯(cuò)渠羞。這是因?yàn)樽宇悰](méi)有自己的this對(duì)象敢茁,而是繼承父類的this對(duì)象译打,然后對(duì)其進(jìn)行加工耗拓。如果不調(diào)用super方法,子類就得不到this對(duì)象奏司。
class ColorPoint extends Point {
constructor(x, y, color) {
super(x, y); // 調(diào)用父類的constructor(x, y)
this.color = color;
}
toString() {
return this.color + ' ' + super.toString(); // 調(diào)用父類的toString()
}
}
super這個(gè)關(guān)鍵字乔询,既可以當(dāng)作函數(shù)使用,也可以當(dāng)作對(duì)象使用韵洋。在這兩種情況下竿刁,它的用法完全不同。
第一種情況搪缨,super作為函數(shù)調(diào)用時(shí)食拜,代表父類的構(gòu)造函數(shù)。
class A {
constructor() {
console.log(new.target.name);
}
}
class B extends A {
constructor() {
super();
}
}
new A() // A
new B() // B
注意副编,super雖然代表了父類A的構(gòu)造函數(shù)负甸,但是返回的是子類B的實(shí)例,即super內(nèi)部的this指的是B痹届,因此super()在這里相當(dāng)于
A.prototype.constructor.call(this)
作為函數(shù)時(shí)呻待,super()只能用在子類的構(gòu)造函數(shù)之中,用在其他地方就會(huì)報(bào)錯(cuò)队腐。
第二種情況蚕捉,super作為對(duì)象時(shí),在普通方法中柴淘,指向父類的原型對(duì)象迫淹;在靜態(tài)方法中,指向父類悠就。
ES6 規(guī)定千绪,通過(guò)super調(diào)用父類的方法時(shí)充易,super會(huì)綁定子類的this梗脾。
class A {
constructor() {
this.x = 1;
}
print() {
console.log(this.x);
}
}
class B extends A {
constructor() {
super();
this.x = 2;
}
m() {
super.print();
}
}
let b = new B();
b.m() // 2
上面代碼中,super.print()雖然調(diào)用的是A.prototype.print()盹靴,但是A.prototype.print()會(huì)綁定子類B的this炸茧,導(dǎo)致輸出的是2瑞妇,而不是1。也就是說(shuō)梭冠,實(shí)際上執(zhí)行的是super.print.call(this)辕狰。
由于綁定子類的this,所以如果通過(guò)super對(duì)某個(gè)屬性賦值控漠,這時(shí)super就是this蔓倍,賦值的屬性會(huì)變成子類實(shí)例的屬性。
class A {
constructor() {
this.x = 1;
}
}
class B extends A {
constructor() {
super();
this.x = 2;
super.x = 3;
console.log(super.x); // undefined
console.log(this.x); // 3
}
}
let b = new B();
上面代碼中盐捷,super.x賦值為3偶翅,這時(shí)等同于對(duì)this.x賦值為3。而當(dāng)讀取super.x的時(shí)候碉渡,讀的是A.prototype.x聚谁,所以返回undefined。