__proto__在跨realm场景下不可靠,因其依赖当前执行环境的object构造函数,而不同realm的object.prototype互不相等,导致访问或修改__proto__失效或引发副作用;应改用object.getprototypeof()等标准api。

__proto__ 不是标准推荐的原型访问方式,尤其在跨 Realm(如 iframe、Worker、不同 JS 执行环境)场景下,它会完全失效或产生不可靠行为。
为什么 __proto__ 在跨 Realm 中不可靠
__proto__ 是一个可读写的访问器属性,指向对象的内部 [[Prototype]]。但它依赖当前执行环境中的 Object 构造函数和原型链解析机制。当对象来自另一个 Realm 时:
- 该对象的内部 [[Prototype]] 指向的是**对方 Realm 的 Object.prototype**,而非当前 Realm 的;
- 当前 Realm 的 Object.prototype !== 对方 Realm 的 Object.prototype,二者是完全不同的对象;
- 因此 obj.__proto__ === Object.prototype 总是 false,即使 obj 是对方 Realm 中的普通对象;
- 修改 obj.__proto__ 可能静默失败,或意外改变当前 Realm 的原型链,引发难以追踪的副作用。
与标准方法的对比
相比 __proto__,更安全的替代方案有:
- Object.getPrototypeOf(obj):标准 API,能正确返回任意 Realm 中对象的 [[Prototype]];
- Object.prototype.isPrototypeOf.call(proto, obj):可跨 Realm 判断原型关系,不依赖构造函数;
- instanceof 和 constructor 都会因 Realm 隔离而失效,不能用于跨环境判断。
实际影响示例
假设 iframe 中创建了数组:const arr = iframe.contentWindow.Array.from([1,2,3]);
-
arr.__proto__ === Array.prototype→ false(跨 Realm,原型不等); -
Object.getPrototypeOf(arr) === iframe.contentWindow.Array.prototype→ true; -
Array.prototype.isPrototypeOf(arr)→ false(因为调用的是当前 Realm 的 Array.prototype); - 但
iframe.contentWindow.Array.prototype.isPrototypeOf(arr)→ true。
建议做法
永远避免直接读写 __proto__,尤其在涉及多上下文的场景中:
- 用
Object.getPrototypeOf()替代obj.__proto__获取原型; - 用
Object.setPrototypeOf()(谨慎)替代赋值__proto__; - 判断继承关系优先使用
isPrototypeOf()或instanceof(仅限同 Realm); - 跨 Realm 类型检测应改用
Object.prototype.toString.call()。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











