super关键字
在 JavaSCript 中,能通过 extends 关键字去继承父类
super 关键字在子类中有以下用法:
- 当成函数调用 super()
- 作为 "属性查询" super.prop 和 super[expr]
super()
super 作为函数调用时,代表父类的构造函数。
ES6 要求,子类的构造函数必须执行一次 super() 函数。
注意:作为函数时,super() 只能用在子类的构造函数之中,用在其他地方就会报错。
javascript
class A {}
class B extends A {
constructor() {
super();
}
}
super 作为函数调用时,内部的 this 指的是子类实例。
javascript
class A {
constructor() {
this.print();
}
print(){
console.log('这是A');
}
}
class B extends A {
constructor() {
super();
}
print(){
console.log('这是B');
}
}
new B() // 这是B
javascript
// 继承了A的print
class A {
constructor() {
this.print();
}
print(){
console.log('这是A');
}
}
class B extends A {
constructor() {
super();
}
}
new B() // 这是A
super.prop
- 在普通方法中,指向父类的原型对象;
- 在静态方法中,指向父类。
普通方法
这里的super指向父类原型对象,即 A.prototype
javascript
class A {
x = 2
p() {
return this.x;
}
}
class B extends A {
print(){
console.log(super.p())
}
}
const a = new B()
a.print() // 2
由于在普通方法中的 super 指向父类的原型对象,而A的CLASS写法其实是:
javascript
function A() {
this.x = 2;
}
A.prototype.print = function () {
return this.x
};
所以我们能够在父类A的原型对象上找到print方法。那么如果是这样:
javascript
class A {
x = 2
}
class B extends A {
print(){
console.log(super.x)
}
}
const a = new B()
a.print() // undefined
自2022年之后,实例属性现在除了可以定义在constructor()方法里面的this上面,也可以定义在类内部的最顶层。所以这里的x=2其实等同于constructor(){this.x = 2};
如果父类上的方法或属性是定义在实例上的,就无法通过 super 调用的
在子类普通方法中通过 super 调用父类的方法时,方法内部的 this 指向的是当前的子类实例。
javascript
class A {
constructor() {
this.x = 1;
}
print() {
console.log(this.x);
}
}
class B extends A {
constructor() {
super();
this.x = 2;
super.y = 123; //如果通过super对某个属性赋值,这时super就是this,赋值的属性会变成子类实例的属性。
}
m() {
super.print();
}
}
let b = new B();
b.m() // 2
console.log(b.y); //123
静态方法
super作为对象,用在静态方法之中,这时 super 将直接指向父类,而不是父类的原型对象。
javascript
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
在子类的静态方法中通过 super 调用父类的方法时,方法内部的 this 指向当前的子类,而不是子类的实例。
javascript
class A {
constructor() {
this.x = 1;
}
static print() {
console.log(this.x);
}
}
class B extends A {
constructor() {
super();
this.x = 2;
}
static m() {
super.print();
}
}
B.x = 3;
B.m() // 3