1. 程式人生 > >es6 super關鍵字

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的例項。