es6 super關鍵字
http://es6.ruanyifeng.com/#docs/class-extends
super關鍵字,既可以當作函式使用,也可以當作物件使用。這倆種的使用是不一樣的
第一種:函式使用
代表父類的建構函式。ES6規定,子類的建構函式,必須執行一次super()函式
注意,super
雖然代表了父類A
的建構函式,但是返回的是子類B
的例項,即super
內部的this
指的是B
,因此super()
在這裡相當於A.prototype.constructor.call(this)
。
1 class A { 2 constructor() {3 console.log(new.target.name); 4 } 5 } 6 class B extends A { 7 constructor() { 8 super(); 9 } 10 } 11 new A() // A 12 new B() // B
第二種:super
作為物件時,在普通方法中,指向父類的原型物件;在靜態方法中,指向父類。
1 class A { 2 p() { 3 return 2; 4 } 5 } 6 7 class B extends A { 8 constructor() {9 super(); 10 console.log(super.p()); // 2 11 } 12 } 13 14 let b = new B();
ES6 規定,在子類普通方法中通過super
呼叫父類的方法時,方法內部的this
指向當前的子類例項。
1 class A { 2 constructor() { 3 this.x = 1; 4 } 5 print() { 6 console.log(this.x); 7 } 8 } 9 10 class B extends A { 11 constructor() {12 super(); 13 this.x = 2; 14 } 15 m() { 16 super.print(); 17 } 18 } 19 20 let b = new B(); 21 b.m() // 2
上面程式碼中,super.print()
雖然呼叫的是A.prototype.print()
,但是A.prototype.print()
內部的this
指向子類B
的例項,導致輸出的是2
,而不是1
。也就是說,實際上執行的是super.print.call(this)
。
由於this
指向子類例項,所以如果通過super
對某個屬性賦值,這時super
就是this
,賦值的屬性會變成子類例項的屬性。
1 class A { 2 constructor() { 3 this.x = 1; 4 } 5 } 6 7 class B extends A { 8 constructor() { 9 super(); 10 this.x = 2; 11 super.x = 3; 12 console.log(super.x); // undefined 13 console.log(this.x); // 3 14 } 15 } 16 17 let b = new B();
上面程式碼中,super.x
賦值為3
,這時等同於對this.x
賦值為3
。而當讀取super.x
的時候,讀的是A.prototype.x
,所以返回undefined
。
如果super
作為物件,用在靜態方法之中,這時super
將指向父類,而不是父類的原型物件。
1 class Parent { 2 static myMethod(msg) { 3 console.log('static', msg); 4 } 5 6 myMethod(msg) { 7 console.log('instance', msg); 8 } 9 } 10 11 class Child extends Parent { 12 static myMethod(msg) { 13 super.myMethod(msg); 14 } 15 16 myMethod(msg) { 17 super.myMethod(msg); 18 } 19 } 20 21 Child.myMethod(1); // static 1 22 23 var child = new Child(); 24 child.myMethod(2); // instance 2
上面程式碼中,super
在靜態方法之中指向父類,在普通方法之中指向父類的原型物件。
另外,在子類的靜態方法中通過super
呼叫父類的方法時,方法內部的this
指向當前的子類,而不是子類的例項。
1 class A { 2 constructor() { 3 this.x = 1; 4 } 5 static print() { 6 console.log(this.x); 7 } 8 } 9 10 class B extends A { 11 constructor() { 12 super(); 13 this.x = 2; 14 } 15 static m() { 16 super.print(); 17 } 18 } 19 20 B.x = 3; 21 B.m() // 3
上面程式碼中,靜態方法B.m
裡面,super.print
指向父類的靜態方法。這個方法裡面的this
指向的是B
,而不是B
的例項。