
深入理解ES6父子继承中的this指向和执行顺序
ES6中的继承机制有时会令人困惑,尤其涉及this指向和执行顺序。本文将通过代码示例,详细分析这两个关键问题。
class Parent {
constructor() {
console.log('parent constructor', this.name);
this.init();
this.logNum = this.logNum.bind(this);
}
name = (() => {
console.log('Parent name init');
return 'Parent';
})();
num = -1;
init() {
console.log('parent init', this.name);
}
logNum() {}
}
class Child extends Parent {
constructor() {
console.log('Child constructor');
super();
console.log('super exec finish', this.num);
}
name = 'Child';
num = (() => {
console.log('Child num init');
return 99;
})();
init() {
console.log('Child init', this.name);
super.init();
this.num = 10;
}
logNum() {
console.log(this.num);
}
}
const { logNum } = new Child();
logNum();
问题一:Parent构造函数中this.name为何为'Parent'?
在Child实例化过程中,首先执行Parent的构造函数。虽然this在Parent构造函数内部指向Child实例,但name属性的初始化发生在构造函数执行之前。此时,this指向的是Parent的原型,因此name的值为'Parent'。
问题二:实例属性(例如x = 'a')的初始化时机?
实例属性的初始化发生在构造函数执行之前。当Parent构造函数调用super()时,会先执行父类的构造函数,初始化父类的实例属性;之后,才会执行子类的构造函数,初始化子类的实例属性。
总结:ES6继承中属性初始化顺序
- 父类类字段初始化(静态属性)
- 父类构造函数初始化实例属性
- 子类类字段初始化(静态属性)
- 子类构造函数初始化实例属性
通过以上分析,我们对ES6父子继承中的this指向和执行顺序有了更清晰的理解,有助于避免潜在的错误。





