ES6类继承构造函数返回对象时方法丢失问题及解决办法咨询
问题:子类方法丢失,父类构造返回对象时调用了错误的方法
问题场景
以下代码中,期望调用A2::method(),但实际执行的是A0::method()。测试发现当父类A1的构造函数返回对象时,子类A2的公共属性会保留,但所有方法都会丢失。
class A0 { method() { return "from A0 " + this.prop } } class A1 { constructor() { return new A0; } } class A2 extends A1 { constructor(v) { super() console.log('here') this.prop = v; } prop = 42; method() { return "from A2 " + this.prop } } const a = new A2(42); console.log(a.prop, a.method())
实际结果
[LOG]: "here" [LOG]: 42, "from A0 42"
预期结果
[LOG]: "here" [LOG]: 42, "from A2 42"
原因分析
在ES6类继承机制中,当父类构造函数返回对象类型的值时,这个返回值会直接替代原本应该创建的子类实例对象。也就是说,new A2()最终得到的是A1构造返回的A0实例,而非A2的实例:
A2的类方法挂载在A2.prototype上,但当前实例属于A0,其原型链指向A0.prototype,自然找不到A2的方法;- 类的公共属性(如
prop = 42)是在构造函数执行时直接赋值到this上的,而这里的this就是super()返回的A0实例,所以属性能被正常赋值并保留。
解决办法
方案1:修改父类构造,避免返回外部对象(推荐)
如果业务逻辑允许,直接去掉A1构造函数中的return new A0;,让构造函数默认返回当前实例,这样子类A2的实例会正常继承原型链,方法和属性都能正常工作:
class A1 { constructor() { // 移除return语句,默认返回this } }
方案2:手动将子类方法绑定到父类返回的对象上
若必须让A1构造返回A0实例,可以在A2的构造函数中,接收super()返回的A0对象,手动将A2的方法挂载到该对象上:
class A2 extends A1 { constructor(v) { // 接收super返回的A0实例 const instance = super(); console.log('here'); // 赋值属性 instance.prop = v; // 将A2的方法绑定到实例上 instance.method = () => { return "from A2 " + instance.prop; }; // 返回修改后的实例 return instance; } }
或者使用bind确保this指向正确:
class A2 extends A1 { constructor(v) { const instance = super(); console.log('here'); instance.prop = v; instance.method = this.method.bind(instance); return instance; } method() { return "from A2 " + this.prop } }
注意:这种方式会给每个实例创建独立的方法副本,可能存在性能损耗,仅适合特殊场景。
内容的提问来源于stack exchange,提问作者Guile
相关产品推荐
相关产品推荐

