Class继承中super

super这个关键字,既可以当作函数使用,也可以当作对象使用。在这两种情况下,它的用法完全不同。
1、super作为函数调用
super作为 函数 调用时,代表 父类的构造函数 。ES6 要求,子类的构造函数必须执行一次super函数。
class A {}
class B extends A {  
    constructor() {    
         super();  
    }
}
上面代码中,子类B的构造函数之中的super(),代表调用父类的构造函数。这是必须的,否则 JavaScript 引擎会报错。

2、super作为对象
super作为 对象 时,在 普通方法 中,指向父类的原型对象;在 静态方法 中,指向父类。
为什么不同的方法中super的指向不同呢?ES6中定义super相当于指向对象原型的指针,即super=>Object.getPrototypeOf(this)。
在来看一下方法的定义:具有功能而非数据的对象属性,内部有[[HomeObject]]属性来包容这个方法从属的对象。
所以在方法中使用super时,super的引用即是通过[[HomeObject]]来确定的:
  1. 在[[HomeObject]]上调用Object.getPrototypeOf()找到原型,super指向该原型;
  2. 在该原型上找到同名方法;
  3. 绑定this;
下面来看两个例子: 
例1:普通方法
class A {
  p() {
    return 2;
  }
}

class B extends A {
  constructor() {
    super();
    console.log(super.p()); // 2
  }
}

let b = new B();
上面代码中,子类B当中的super.p()在constructor方法中,constructor的[[HomeObject]]为B.prototype,所以super=>Object.getPrototypeOf(B.prototype)=>A.prototype,即super指向A.prototype,所以super.p()就相当于A.prototype.p()。
这里需要注意,由于super指向父类的原型对象,所以定义在父类实例上的方法或属性,是无法通过super调用的。
下面看第二个例子:
例2:静态方法
class Parent {
  static myMethod(msg) {
    console.log('static', msg);
  }

  myMethod(msg) {
    console.log('instance', msg);
  }
}

class Child extends Parent {
  static myMethod(msg) {
    super.myMethod(msg);
  }

  myMethod(msg) {
    super.myMethod(msg);
  }
}

Child.myMethod(1); // static 1

var child = new Child();
child.myMethod(2); // instance 2
在静态方法之中,静态方法的[[HomeObject]]为B,所以super=>Object.getPrototypeOf(B)=>B.prototype=>A.instance,即super指向A的实例,所以这时super将指向父类A,而不是父类的原型对象。 



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值