为何从父类构造函数调用的方法无法设置子类私有字段?
子类私有字段在父类构造器调用的方法中无法访问的原因
代码示例
class Superclass { constructor() { this.setPrivateField(); } setPrivateField() { // No implementation } } class Subclass extends Superclass { #field; setPrivateField() { console.log(this); this.#field = 1; } } new Subclass();
控制台输出
Subclass {} test.js:16 this.#field = 1; ^ TypeError: Cannot write private member #field to an object whose class did not declare it at Subclass.setPrivateField (test.js:16:17) at new Superclass (test.js:5:10) at new Subclass (test.js:12:1) at Object.<anonymous> (test.js:20:1) at Module._compile (node:internal/modules/cjs/loader:1434:14) at Module._extensions..js (node:internal/modules/cjs/loader:1518:10) at Module.load (node:internal/modules/cjs/loader:1249:32) at Module._load (node:internal/modules/cjs/loader:1065:12) at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:158:12) at node:internal/main/run_main_module:30:49 Node.js v22.2.0
问题疑问
#field字段在Subclass中声明,且控制台已确认对象类型为Subclass,为何会触发该TypeError?原以为是V8引擎的bug,但Firefox浏览器中也存在相同表现。
原因解析
这不是引擎bug,而是JavaScript类继承的初始化顺序规则导致的:
- 执行
new Subclass()时,会先调用父类Superclass的构造器,此时子类自身的构造逻辑还未启动。 - 父类构造器调用
this.setPrivateField(),由于this指向Subclass实例,实际执行的是子类的同名方法。 - 但子类的私有字段#field是在子类构造器执行阶段才会绑定到实例上,此时父类构造器仍在运行,子类的初始化步骤(包括私有字段的创建)尚未完成,实例上并没有#field这个私有成员。
- 虽然
console.log(this)显示实例类型是Subclass,但私有字段的存在与否不影响实例的类型标识,此时尝试给未初始化的私有字段赋值,就会触发TypeError。
简单总结:父类构造器先执行,子类私有字段还未被创建,调用子类方法赋值自然找不到对应的私有成员。
内容的提问来源于stack exchange,提问作者Natalie Weizenbaum
相关产品推荐
相关产品推荐

