ES6 Class 中的 super 关键字

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

1、当作函数使用

class Sup {}
class Sub extends Sup {
    constructor() {
        super(); //ES6 要求,子类的构造函数必须执行一次super函数。
    }
}

super()在这里相当于 A.prototype.constructor.call(this)super虽然代表了父类Sup的构造函数,但是返回的是子类Sub的实例,即super内部的this指的是Sub

class Sup {
    constructor() {
        console.log(new.target.name); //new.target指向当前正在执行的函数
    }
}
class Sub extends Sup {
    constructor() {
        super();
    }
}
new Sup() // A
new Sub() // B

可以看到,在super()执行时,它指向的是子类Sub的构造函数,而不是父类Sup的构造函数。也就是说,super()内部的this指向的是Sub

2、当作对象使用

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

class Sup {
   c() {
       return 2;
   }
}
class Sub extends Sup {
    constructor() {
        super();
        console.log(super.c()); // 2
     }
}
let b = new Sub();

上面代码中,子类Sub当中的super.c(),就是将super当作一个对象使用。这时,super在普通方法之中,指向Sup.prototype,所以super.c()就相当于Sup.prototype.c()。通过super调用父类的方法时,super会绑定子类的this

class Sup {
    constructor() {
         this.x = 1;
     }
     s() {
         console.log(this.x);
     }
}
class Sub extends Sup {
    constructor() {
        super();
        this.x = 2;
    }
    m() {
        super.s();
    }
}
let b = new Sub();
b.m() // 2

上面代码中,super.s()虽然调用的是Sup.prototype.s(),但是Sup.prototype.s()会绑定子类Subthis,导致输出的是2,而不是1。也就是说,实际上执行的是super.s.call(this)
由于绑定子类的this,所以如果通过super对某个属性赋值,这时super就是this,赋值的属性会变成子类实例的属性。

class Sup {
    constructor() {
        this.x = 1;
    }
}
class Sub extends Sup {
    constructor() {
        super();
        this.x = 2;
        super.x = 3;
        console.log(super.x); // undefined
        console.log(this.x); // 3
    }
}
let b = new Sub();

上面代码中,super.x赋值为3,这时等同于对this.x赋值为3。而当读取super.x的时候,读的是Sup.prototype.x,所以返回undefined
使用super的时候,必须显式指定是作为函数、还是作为对象使用,否则会报错。

你可能感兴趣的:(ES6 Class 中的 super 关键字)