__proto__ 指向对象原型但跨上下文(如 iframe)时失效,导致 instanceof 失败、手动赋值无效;应改用 object.prototype.tostring.call() 或 array.isarray() 等安全检测方式。

__proto__ 是对象内部的一个访问器属性(非标准但被广泛支持),指向该对象的原型(即其构造函数的 prototype 对象)。它在跨上下文对象(如 iframe、Worker、不同 JS 执行环境之间)时表现异常——无法正确共享或识别原型链,这是关键限制。
跨上下文对象的 __proto__ 不互通
当一个对象从 iframe 或另一个 window 实例中传入当前页面(例如通过 postMessage 或直接引用 iframe.contentWindow 的对象),它的 __proto__ 仍指向原上下文中的原型对象。而当前上下文没有该原型的“副本”,导致:
- 用
instanceof判断会失败(如obj instanceof Array返回false,即使 obj 是 iframe 里传来的数组) - 调用
obj.__proto__.constructor得到的是另一全局环境下的构造函数,与当前环境的Array、Date等不相等 - 手动修改
obj.__proto__ = Array.prototype无效——因为两个环境的Array.prototype是不同对象(===为false)
typeof 和 Object.prototype.toString.call 更可靠
面对跨上下文对象,应避免依赖 __proto__ 或 instanceof,改用类型检测的通用方案:
-
typeof obj === 'object'只能区分基本类型,对对象帮助有限 -
Object.prototype.toString.call(obj)是最稳妥方式:它不依赖当前环境的原型,而是读取对象内部的[[Class]]标签
例如:Object.prototype.toString.call(iframeArray)仍返回"[object Array]" - 对常见内置类型,可结合
Array.isArray()、isFinite()、obj instanceof window.Array(注意必须用目标 window 的构造器)
不能靠 __proto__ 实现跨上下文继承
试图让当前环境的对象继承 iframe 中某个类的原型链是行不通的:
-
obj.__proto__ = iframeWin.MyClass.prototype—— 赋值虽成功,但方法内this若访问其他 iframe 内对象或全局变量,会因作用域隔离而报错或行为异常 - 方法体内的闭包、
this.constructor、super等都绑定在原上下文,无法自然迁移 - 真正可行的做法是:在当前上下文重新定义类,或使用数据序列化(
JSON.stringify/parse)+ 显式重建
现代替代方案:优先使用 Reflect.getPrototypeOf / Object.getPrototypeOf
__proto__ 已被标记为废弃(尽管未移除)。跨上下文场景下更应使用标准 API:
-
Object.getPrototypeOf(obj)安全获取原型,但它在跨上下文时返回的仍是原环境原型对象——只是语义更清晰 -
Reflect.getPrototypeOf(obj) === Reflect.getPrototypeOf([])依然为false,提醒你原型不可跨环境比较 - 若需统一处理,建议封装类型判断工具函数,内部基于
toString.call+ 构造器名称白名单
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











