super关键字

2020-08-11  本文已影响0人  zhulichao
super关键字,既可以当作函数使用,也可以当作对象使用。使用super的时候,必须显式指定是作为函数、还是作为对象使用,否则会报错。由于对象总是继承其他对象的,所以可以在任意一个对象中,使用super关键字。

```
class A {}
class B extends A {
  constructor() {
    super();
    /*
    Uncaught SyntaxError: 'super' keyword unexpected here
    无法看出super是作为函数使用,还是作为对象使用
    */
    console.log(super);
    /*
    super.valueOf()表明super是一个对象
    */
    console.log(super.valueOf() instanceof B); // true
  }
}

var obj = {
  toString() {
    return "MyObject: " + super.toString();
  }
};
obj.toString(); // MyObject: [object Object]
```

第一种情况,当作函数使用,代表父类的构造函数,super虽然代表了父类的构造函数,但是返回的是子类的实例,即super内部的this指的是子类。super()只能用在子类的构造函数中,用在其它地方就会报错。ES6要求,子类的构造函数必须执行一次super函数。

```
class A{}
class B extends A {
    constructor() {
        /*
        当作函数使用,代表父类的构造函数,相当于
        A.prototype.constructor.call(this)
        */
        super();
    }
}
```

第二种情况,super作为对象时,在普通方法中指向父类的原型对象,在静态方法中指向父类。ES6规定,通过super调用父类的方法时,super会绑定子类的this。由于绑定子类的this,所以如果通过super对某个属性赋值,这时super就是this,赋值的属性会变成子类实例的属性。

```
class A {
  constructor() {
    this.q = 2;
  }
  p() {
    return 2;
  }
  print() {
    /*
    通过B的super.print()虽然调用的是A.prototype.print(),但是A.prototype.print()会绑定子类B的this,相当于
    super.print.call(this)
    */
    console.log(this.q);
  }
}
class B extends A {
  constructor() {
    super();
    this.q = 3;
    /*
    当作对象使用,这是普通方法,super指向A.prototype,相当于
    A.prototype.p()
    q是父类A实例的属性,super.q就引用不到它
    */
    console.log(super.p()); // 2
    console.log(super.q); // undefined
  }
  subPrint() {
    super.print();
  }
}
let b = new B();
b.subPrint(); // 3
```

```
class Parent {
  static myMethod(msg) {
    console.log('static', msg);
  }
  myMethod(msg) {
    console.log('instance', msg);
  }
}

class Child extends Parent {
  static myMethod(msg) {
    // 静态方法,super指向父类
    super.myMethod(msg);
  }
  myMethod(msg) {
    // 普通方法,super指向父类的原型对象
    super.myMethod(msg);
  }
}

Child.myMethod(1); // static 1
var child = new Child();
child.myMethod(2); // instance 2
```
上一篇下一篇

猜你喜欢

热点阅读