constructor会丢失,因为重写原型后新对象自身无constructor属性,需沿原型链向上查找,最终指向父类构造函数;修复方式包括显式赋值、object.defineproperty或使用es6 class自动处理。

当通过赋值新对象重写原型链(如 Sub.prototype = new Super() 或 Sub.prototype = Object.create(Super.prototype))后,Sub.prototype.constructor 会指向 Super 而非 Sub。这是因为在原型对象被替换时,原 Sub.prototype.constructor(默认指向 Sub)也随之丢失。修复的关键是手动将 constructor 属性重新指回子类构造函数。
为什么 constructor 会丢失
每个函数的 prototype 对象默认有一个 constructor 属性,指向该函数本身。但当你执行:
Sub.prototype = Object.create(Super.prototype);
此时 Sub.prototype 是一个以 Super.prototype 为原型的新对象,它自身没有 constructor 属性,于是沿原型链向上查找到 Super.prototype.constructor —— 即 Super。这就导致 new Sub().constructor === Super,不符合预期。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
修复 constructor 的三种常用方式
-
显式赋值 constructor:在重写原型后立即设置
Sub.prototype = Object.create(Super.prototype);<br> Sub.prototype.constructor = Sub;
-
使用 Object.defineProperty(推荐):确保
constructor可枚举性与原生行为一致(默认不可枚举)Object.defineProperty(Sub.prototype, 'constructor', {<br> value: Sub,<br> enumerable: false,<br> writable: true,<br> configurable: true<br> }); -
ES6 class 中无需手动修复:class 语法底层已自动处理,
extends后子类的prototype.constructor始终正确指向自身,不依赖显式赋值。
不修复会有什么影响
多数业务逻辑不受影响,但以下场景可能出问题:
- 通过实例的
constructor属性做类型判断(如obj.constructor === Sub)会失败; - 某些序列化/反序列化库、依赖
constructor.name的工具或调试器显示错误构造函数名; - 继承链中若子类还继续派生,且后续也依赖
constructor,错误会逐层传递。
实际建议
如果使用 ES5 风格手写继承,每次重写 prototype 后都应修复 constructor,优先用 Object.defineProperty 保证属性特性匹配原生行为。若项目已支持 ES6,直接使用 class 和 extends,既语义清晰又避免此类细节陷阱。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










