原型继承中constructor丢失本质是原型链被覆盖或截断,导致查到object.prototype.constructor;修复关键在还原原型链结构并稳定构造函数引用,避免字面量直接赋值、用defineproperty保护、修复断裂链、proxy中正确使用reflect.construct,且判断类型应优先用instanceof而非constructor。

原型继承中 constructor 丢失,本质不是属性“消失”了,而是原型链被覆盖或截断,导致实例顺着原型链向上查时,最终落到 Object.prototype.constructor 上,显示为 Object。修复重点不在强行改 constructor,而在还原正确的原型链结构,并让构造函数引用稳定存在。
避免字面量赋值直接覆盖 prototype
用对象字面量整体替换原型是最常见诱因:
- 错误写法:
MyClass.prototype = { say() {} };→ 新对象无constructor,查到Object - 正确做法一(内联声明):
MyClass.prototype = { constructor: MyClass, say() {} }; - 正确做法二(defineProperty 保护):
Object.defineProperty(MyClass.prototype, 'constructor', {<br> value: MyClass,<br> writable: true,<br> configurable: true,<br> enumerable: false<br>});
这样既修正指向,又避免被for...in或Object.assign意外覆盖
修复已断裂的实例原型链
旧库或编译工具(如早期 Babel)可能用 Object.create(null) 或直接操作 __proto__,造成实例的 [[Prototype]] 指向 null 或 Object.prototype:
- 先验证:
Object.getPrototypeOf(obj)返回null或Object.prototype,就说明链断了 - 分两步修复:
① 用Object.setPrototypeOf(obj, MyClass.prototype)重接原型链
② 确保MyClass.prototype.constructor === MyClass;若不成立,再手动赋值
Proxy 代理类继承时别丢 new.target
子类继承被 Proxy 包裹的父类,若 construct 陷阱里只写 new _class(args),新对象的 [[Prototype]] 会错配到父类原型:
- 错误:
return new _class(args); - 正确:
return Reflect.construct(_class, args, constructor);
第三个参数显式传入new.target,确保实例原型指向子类prototype,constructor 自然回归
类型判断别依赖 constructor
即使修好了 constructor,它仍是可写属性,任何代码都可能篡改:
- 不要用:
obj.constructor === MyClass - 推荐用:
obj instanceof MyClass(基于真实原型链,不可伪造) - 或:
MyClass.prototype.isPrototypeOf(obj) - 需要字符串标识时,可用
obj.constructor?.name,但仅作日志或调试参考











