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

猜你喜欢

转载自www.cnblogs.com/zhaobao1830/p/9944991.html
今日推荐