es6的类继承(Class Extends)
Last Updated:2022-10-31
子类的constructor
里头第一行一定要调用一下super()
为什么子类的构造函数,一定要调用
super()
?原因就在于 ES6 的继承机制,与 ES5 完全不同。ES5 的继承机制,是先创造一个独立的子类的实例对象,然后再将父类的方法添加到这个对象上面,即“实例在前,继承在后”。ES6 的继承机制,则是先将父类的属性和方法,加到一个空的对象上面,然后再将该对象作为子类的实例,即“继承在前,实例在后”。这就是为什么 ES6 的继承必须先调用super()
方法,因为这一步会生成一个继承父类的this
对象,没有这一步就无法继承父类。
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
class ColorPoint extends Point {
constructor(x, y, color) {
this.color = color; // ReferenceError
super(x, y);
this.color = color; // 正确
}
}
如果子类没有定义constructor()
方法,这个方法会默认添加,并且里面会调用super()
也就是说,不管有没有显式定义,任何一个子类都有constructor()
方法。
Object.getPrototypeOf()
来从子类上获取父类
class Point { /*...*/ }
class ColorPoint extends Point { /*...*/ }
Object.getPrototypeOf(ColorPoint) === Point
// true
super
关键字在类中使用
如果作为函数使用(super()
),那么代表父类的构造函数
如果在父类的静态函数中以对象的方式使用(super.xx()
,super.xx
),那么代表的是父类这个类(非父类的实例、父类的原型)
如果在父类的普通函数中以对象的方式使用(super.xx()
,super.xx
),那么代表的是父类的原型
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指向当前的子类,而不是子类的实例。
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