You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何ECMAScript中属性初始化无法传递给子类?

ES6类继承中属性赋值被覆盖的原因与解释

你的问题核心在于ES6类实例化过程中,父类构造函数与子类实例属性初始化的执行顺序,下面结合你的代码拆解具体逻辑:

一、ClassWithProp的情况(无自定义构造函数的子类)

当你执行new ClassWithProp(properties)时,JS引擎的执行步骤是:

  1. 创建子类实例对象,绑定好原型链。
  2. 自动调用父类构造函数super(properties)(因为子类没有自定义constructor,JS会生成默认构造函数,直接传递参数给super)。
  3. 进入父类BaseClass的构造函数:通过Object.assign(this, properties)把传入的属性值(childInitializedProp:20等)赋值给实例,这时候构造函数内的console.log能看到正确的赋值结果。
  4. 父类构造函数执行完毕后,子类的实例属性初始化代码会立刻执行——也就是类体里的childUnitializedProp;(等价于给实例赋值undefined)和childInitializedProp = 1;,这两步直接覆盖了父类构造函数里已经赋好的对应属性值。
  5. 所以外部的console.log(initedObj)看到的是子类初始化后的属性值,而非父类构造函数中设置的结果。

二、ClassWithOwnAssign的情况(有自定义构造函数的子类)

当执行new ClassWithOwnAssign(properties)时,执行顺序变成:

  1. 创建子类实例对象,绑定原型链。
  2. 调用super()(这里没传参数给父类,所以父类构造函数里的Object.assign没生效)。
  3. 执行子类的实例属性初始化:childUnitializedProp = undefined、childInitializedProp = 1。
  4. 执行构造函数中super()之后的代码:Object.assign(this, properties),把传入的属性值赋值给实例,这时候会覆盖子类初始化的属性值。
  5. 所以外部console.log能看到预期的赋值结果。

三、解决方案

如果想让父类构造函数中的赋值生效,有几种可选方式:

  • 给子类添加自定义构造函数,在super()调用后再执行Object.assign(类似ClassWithOwnAssign的写法),确保父类或外部传入的属性覆盖子类的初始值。
  • 把子类的属性初始化逻辑移到构造函数中,而非类体的顶层,这样可以控制赋值顺序。
  • 调整父类的赋值时机,比如在子类属性初始化完成后再执行(比如通过钩子函数)。

内容的提问来源于stack exchange,提问作者Sol

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 22:03:13