fn.constructor与Object.getPrototypeOf(fn).constructor是否会不一致?
JS 中
obj.constructor与Object.getPrototypeOf(obj).constructor的不一致场景 二者核心的访问逻辑本身就存在差异:
obj.constructor会沿着实例的完整原型链向上查找,返回第一个匹配到的constructor属性值Object.getPrototypeOf(obj).constructor直接读取实例的直接原型上的constructor属性,不会从实例自身开始查找
以下是非常容易出现二者不一致的场景:
场景1:实例自身挂载了自定义constructor属性
这是最常见的不一致场景,对象自有属性的优先级高于原型链属性,直接会覆盖取值:
class Foo {} const myFoo = new Foo(); // 给实例自身添加constructor属性,覆盖原型链上的默认取值 myFoo.constructor = function Bar() {}; const constructor1 = myFoo.constructor; // 输出 Bar const constructor2 = Object.getPrototypeOf(myFoo).constructor; // 输出 Foo // 二者完全不相等
场景2:实例被 Proxy 代理,拦截了constructor属性访问
如果用 Proxy 对实例做了封装,自定义拦截了constructor属性的读取逻辑,就会出现不一致:
class Foo {} const myFoo = new Foo(); const proxyIns = new Proxy(myFoo, { get(target, prop) { if (prop === 'constructor') return Number; return Reflect.get(target, prop); } }); const constructor1 = proxyIns.constructor; // 输出 Number const constructor2 = Object.getPrototypeOf(proxyIns).constructor; // 输出 Foo
序列化场景的开发建议
如果你需要可靠获取实例对应的构造函数用于反序列化,可以参考以下实践:
- 用
Object.hasOwn(obj, 'constructor')先判断实例是否有自定义的自有constructor属性,再根据业务逻辑决定是否采信该值 - 优先使用
Object.getPrototypeOf(obj)?.constructor取值,可以规避实例自定义constructor属性的干扰 - 针对
Object.create(null)创建的无原型实例,要做好空值兜底,避免访问属性时报错
内容的提问来源于stack exchange,提问作者Julian Lachniet
相关产品推荐
相关产品推荐

