ES6中类Class的super关键字

super 关键字,既可以当作函数使用,也可以当作对象使用。在这两种情况下,它的用法完全不同。

1、super当做函数使用

super 作为函数调用时,代表父类的构造函数。ES6 要求,子类的构造函数必须执行一次 super() 函数。注意:作为函数时,super() 只能用在子类的构造函数之中,用在其他地方就会报错。

  1. class A {}
  2. class B extends A {
  3. constructor() {
  4. super();
  5. }
  6. }

super 作为函数调用时,内部的 this 指的是子类实例

  1. class A {
  2. constructor() {
  3. this.show();
  4. }
  5. }
  6. class B extends A {
  7. constructor() {
  8. super();
  9. }
  10. show(){
  11. console.log('实例');
  12. }
  13. static show(){
  14. console.log('子类');
  15. }
  16. }
  17. new B()  //输出 '实例' ,new B 时触发了 B 的构造函数,所以触发了 super 方法,即触发了父类 A 的构造函数,此时的 this.show 的 this 指的是子类

2、super 作为对象使用

super 作为对象时,在普通方法中,指向父类的原型对象;在静态方法中,指向父类。

2.1、super在普通方法中(即非静态方法)及此时的 this 关键字指向

  1. class A {
  2. p() {
  3. return 2;
  4. }
  5. }
  6. class B extends A {
  7. constructor() {
  8. super();
  9. console.log(super.p()); // 2 此时的super指向父类原型对象,即 A.prototype
  10. }
  11. }
  12. let b = new B();  //2

由于在普通方法中的 super 指向父类的原型对象,所以如果父类上的方法或属性是定义在实例上的,就无法通过 super 调用的。如下所示:

  1. class A {
  2. constructor() { //在构造函数上定义的属性和方法相当于定义在父类实例上的,而不是原型对象上
  3. this.p = 2;
  4. }
  5. }
  6. class B extends A {
  7. get m() {
  8. return super.p;
  9. }
  10. }
  11. let b = new B();
  12. console.log(b.m) // undefined

在子类普通方法中通过 super 调用父类的方法时,方法内部的 this 指向的是当前的子类实例。

  1. class A {
  2. constructor() {
  3. this.x = 1;
  4. }
  5. print() {
  6. console.log(this.x);
  7. }
  8. }
  9. class B extends A {
  10. constructor() {
  11. super();
  12. this.x = 2;
  13.    super.y = 123;  //如果通过super对某个属性赋值,这时super就是this,赋值的属性会变成子类实例的属性。
  14. }
  15. m() {
  16. super.print();
  17. }
  18. }
  19. let b = new B();
  20. b.m() // 2
  21. console.log(b.y); //123

2.2、super在静态方法中及此时的 this 关键字指向

super作为对象,用在静态方法之中,这时 super 将直接指向父类,而不是父类的原型对象。

  1. class Parent {
  2. static myMethod(msg) {
  3. console.log('static', msg);
  4. }
  5. myMethod(msg) {
  6. console.log('instance', msg);
  7. }
  8. }
  9. class Child extends Parent {
  10. static myMethod(msg) {
  11. super.myMethod(msg);
  12. }
  13. myMethod(msg) {
  14. super.myMethod(msg);
  15. }
  16. }
  17. Child.myMethod(1); // static 1
  18. var child = new Child();
  19. child.myMethod(2); // instance 2

在子类的静态方法中通过 super 调用父类的方法时,方法内部的 this 指向当前的子类,而不是子类的实例。

    1. class A {
    2. constructor() {
    3. this.x = 1;
    4. }
    5. static print() {
    6. console.log(this.x);
    7. }
    8. }
    9. class B extends A {
    10. constructor() {
    11. super();
    12. this.x = 2;
    13. }
    14. static m() {
    15. super.print();
    16. }
    17. }
    18. B.x = 3;
    19. B.m() // 3