constructor丢失是因原型被替换导致自有constructor属性消失,需用Object.defineProperty手动修复并迁移其他自有属性,或改用class语法避免问题。

constructor 丢失不是“找不到”,而是原型对象被替换后,它原本自带的 constructor 属性没了,导致实例顺着原型链向上查,最终落到父类甚至 Object 上。找回的关键是**手动、正确地把它设回去**。
为什么 constructor 会丢失
函数创建时,JS 引擎自动在它的 prototype 上加一个 constructor 属性,值就是该函数本身。但一旦你用下面任一方式重写原型:
Sub.prototype = { method() {} };Sub.prototype = Object.create(Super.prototype);Sub.prototype = new Super();
新对象没有 constructor 属性,引擎就会沿 __proto__ 往上找——结果常是 Super.prototype.constructor 或 Object.prototype.constructor,于是 new Sub().constructor 不再指向 Sub。
怎么正确修复 constructor 指向
不能简单写 Sub.prototype.constructor = Sub,这会让属性变成可枚举的,影响 for...in 遍历,也不符合原生行为。推荐用 Object.defineProperty 显式定义:
立即学习“Java免费学习笔记(深入)”;
Object.defineProperty(Sub.prototype, 'constructor', {
value: Sub,
enumerable: false,
writable: true,
configurable: true
});
这样修复后:new Sub().constructor === Sub 成立,instanceof 判断也不受影响。
如果原型上还有其他自有属性,也要一并迁移
比如你曾写过 Sub.prototype.version = '2.1' 或 Sub.prototype.init = function(){},这些属性在覆盖 prototype 时全丢了。得提前保存再还原:
- 用
Object.getOwnPropertyDescriptors(Sub.prototype)提取所有自有属性描述符 - 创建新原型(如
Object.create(Super.prototype))后,用Object.defineProperties(newProto, descriptors)批量还原 - 注意跳过
constructor,避免和上面的修复冲突
更省心的替代方案
如果项目支持,优先用现代语法:
- 改用
class Sub extends Super:ES6 class 自动维护constructor和原型链,不用手动修 - 必须用函数式继承时,可用
Object.setPrototypeOf(Sub.prototype, Super.prototype)替代整体赋值,保留原有属性 - 封装一个通用继承工具函数,内部统一处理原型链接、constructor 修复和描述符迁移


















