super关键字既可以当作函数使用,也可以当作对象使用。在这两种情况下,它的用法完全不同。
注意:
1、使用super的时候,必须显式指定是作为函数、还是作为对象使用,否则会报错;
2、由于对象总是继承其他对象的,所以可以在任意一个对象中,使用super关键字。
一、super作为函数调用
当super作为函数调用时,代表父类的构造函数。(ES6要求子类的构造函数必须执行一次super函数,并且只能用在子类的构造函数中)
class A {}
class B extends A {
constructor() {
super();
}
}
注意:super代表的是父类A的构造函数,返回的却是子类B的实例,即super内部的this指的是子类B的实例,因此在这里super()相当于A.prototype.constructor.call(this)
二、super作为对象
class A {
p() {
return 2;
}
}
class B extends A {
constructor() {
super();
console.log(super.p()); // 2
}
}
let b = new B();
1、在普通方法中,super指向父类的原型对象(super指向A.prototype);
注意:
(1)、因为super指向的事父类的原型对象,所以定义在父类实例上的方法或属性(即构造器constructor中定义的属性和方法)无法通过super调用。
(2)、在子类普通方法中通过super调用父类的方法事,方法内部的this指向当前的子类实例,所以如果通过super对某个属性进行赋值,这时super就是this,赋值的属性会变成子类实例的属性。
class A {
constructor() {
this.x = 1;
}
}
class B extends A {
constructor() {
super();
this.x = 2;
super.x = 3; // super.x 等同于 this.x
console.log(super.x); // undefined (super.x 等同于 A.prototype.x)
console.log(this.x); // 3
}
}
let b = new B();
2、在静态方法中,super指向父类。
注意:在子类的静态方法中通过super调用父类的方法时,方法内部的this指向当前的子类