Object.getPrototypeOf(obj)返回对象真实[[Prototype]],与constructor无关;constructor.prototype是推导值,易被篡改失真,二者不自动同步,需手动维护一致。

Object.getPrototypeOf(obj) 和 obj.constructor 指向的原型,本质上是两条独立路径:前者读取对象内部 [[Prototype]],后者依赖可被篡改的 constructor 属性。它们不会自动同步,必须手动维护一致。
Object.getPrototypeOf 返回的是真实原型链节点
它直接暴露对象的隐式原型(即 [[Prototype]]),不可伪造、不随 constructor 变动而变化。例如:
class User {}
const u = new User();
console.log(Object.getPrototypeOf(u) === User.prototype); // true无论 u.constructor 是否被改写,Object.getPrototypeOf(u) 始终返回 User.prototype。
constructor.prototype 是推导出来的,容易失真
u.constructor.prototype 的值取决于 u.constructor 是否还指向原始类:
- ✅ 默认情况:
u.constructor === User→u.constructor.prototype === User.prototype - ❌ 被覆盖后:
User.prototype.constructor = null或u.constructor = Array→u.constructor.prototype就不再对应真实原型。
常见导致脱节的操作包括:
- 直接重写
MyClass.prototype = { ... }但没恢复constructor - 使用
Object.assign(MyClass.prototype, {...})覆盖了原有constructor - 框架或工具(如某些 Babel 插件)自动清理
constructor
同步的关键操作只有两个
-
修复 prototype 上的 constructor(推荐在定义类后立即做):
MyClass.prototype.constructor = MyClass;
-
避免直接赋值 prototype,改用 Object.defineProperty 保留 constructor:
Object.defineProperty(MyClass.prototype, 'constructor', { value: MyClass, writable: true, configurable: true, enumerable: false });
判断是否已脱节,可以这样验证
const proto = Object.getPrototypeOf(obj);
if (obj.constructor?.prototype !== proto) {
console.warn('constructor.prototype 与实际原型不一致');
}实际开发中更稳妥的做法
- 类型识别优先用
Object.getPrototypeOf(obj).constructor.name,而不是obj.constructor.name - 创建副本时,用
Object.setPrototypeOf(copy, Object.getPrototypeOf(source))+ 手动设copy.constructor = source.constructor(前提是 source.constructor 未被污染) - 跨 iframe 场景下,
instanceof失效,但Object.getPrototypeOf仍有效,此时更不能依赖constructor.prototype
本质上,Object.getPrototypeOf 是事实来源,constructor 是辅助线索。保持同步不是语言机制,而是编码约定。

















