有如下代码:
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()
打印结果:
Child constructor
Parent name init
parent constructor Parent
Child init Parent
parent init Parent
Child num init
super exec finish 99
99
1、在实例化Child时,Parent.constructor中的name为什么是'Parent'?Child.constructor
中调用super
,内部this
指向为Child
,所以不应该是'Child'吗?
2、诸如x = 'a'的实例属性是什么时候完成初始化的?Child.constructor
中调用super
时,可以看到打印了'Parent name init'
,说明实例属性是在构造器方法之前就初始化了吧,那为什么Child.num
是在super
调用结束后才初始化?
第一问
当实例化Child时,会首先执行父类Parent的构造函数,然后再执行子类Child的构造函数。

在Parent.constructor方法中打断点如下图所示:
从上图Scope栏中的Local作用域可知,虽然this值指向Child,但是其内部的name属性值是“Parent”
原因是类字段初始化发生在构造函数执行之前。当 Parent 的构造函数被调用时,类字段的初始化,也就是表达式赋值
已经发生了。
不妨在Parent中增加如下代码:
实际上还是先对类字段进行初始化,然后再调用构造函数实例化
第二问
当执行 super() 方法时,父类 Parent 的构造函数会执行并初始化父类的实例属性,然后才会继续执行子类 Child 的构造函数。在子类的构造函数中,才会对子类的实例属性比如child.num进行初始化