ES6 父子继承中一些执行顺序以及this指向的问题?

作者站长头像
站长
· 阅读数 13

有如下代码:

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调用结束后才初始化?

回复
1个回答
avatar
test
2024-06-23

第一问

当实例化Child时,会首先执行父类Parent的构造函数,然后再执行子类Child的构造函数。在Parent.constructor方法中打断点如下图所示:answer image从上图Scope栏中的Local作用域可知,虽然this值指向Child,但是其内部的name属性值是“Parent”

  • 原因是类字段初始化发生在构造函数执行之前。当 Parent 的构造函数被调用时,类字段的初始化,也就是表达式赋值

    name = (() => {
      console.log('Parent name init')
      return 'Parent'
    })()

    已经发生了。

  • 虽然this 引用的是 Child 的实例,但是因为表达式赋值是Parent 的构造函数被调用之前执行的,所以 this.name 实际上是在 Child 的实例上设置了一个名为 name 的属性,并赋值为 'Parent'。
  • 不妨在Parent中增加如下代码:

    parentName = "parentName"
    init() {
      console.log('parent init', this.name)  //结果输出parent init Parent
      console.log("test: ", this.parentName) //结果输出test: parentName
    }

    实际上还是先对类字段进行初始化,然后再调用构造函数实例化

第二问

当执行 super() 方法时,父类 Parent 的构造函数会执行并初始化父类的实例属性,然后才会继续执行子类 Child 的构造函数。在子类的构造函数中,才会对子类的实例属性比如child.num进行初始化

回复
likes
适合作为回答的
  • 经过验证的有效解决办法
  • 自己的经验指引,对解决问题有帮助
  • 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
  • 询问内容细节或回复楼层
  • 与题目无关的内容
  • “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容