应优先使用 object.getprototypeof() 而非 __proto__,因其是标准、只读、行为一致的 api;后者是非标准、可写、兼容性差且易引发性能与继承问题。

推荐用 Object.getPrototypeOf() 而不是 __proto__,核心原因是前者是标准、稳定、只读的 API;后者是非标准遗留属性,行为不一致、可写、易引发隐患。
标准性与兼容性更可靠
Object.getPrototypeOf() 是 ECMAScript 5+ 正式规范定义的方法,所有现代环境(浏览器、Node.js)都原生支持,行为统一。而 __proto__ 最初是 Mozilla 的私有扩展,虽然后来被部分引擎实现并写入规范附录(仅作为历史兼容说明),但它不是语言标准接口:
- 在
Object.create(null)创建的对象上,"__proto__" in obj可能返回false(某些环境)或true(另一些环境);但Object.getPrototypeOf(obj)总是返回null,结果确定。 - 严格模式下对
__proto__赋值会静默失败(不报错但无效);而Object.getPrototypeOf()从不修改对象,杜绝副作用。
语义清晰,职责单一
Object.getPrototypeOf(obj) 的作用非常明确:只读取对象内部 [[Prototype]] 指针的值。它不做任何隐式转换或额外逻辑,符合“所见即所得”原则:
- 传入普通对象 → 返回其原型(如
{}返回Object.prototype); - 传入数组 → 返回
Array.prototype,不是Object.prototype; - 传入原始值(如
"abc")→ 先包装为String实例,再返回String.prototype; - 传入
null或undefined→ 直接抛TypeError,错误边界清晰。
避免误用和性能风险
__proto__ 是可写的,但随意修改它会带来实际问题:
- 改变
__proto__可能导致 JS 引擎放弃对对象的优化(如内联缓存失效),拖慢后续属性访问速度; - 在复杂继承链或类继承中,手动改
__proto__容易破坏静态方法继承(比如Child.staticMethod()失效),而Object.getPrototypeOf()完全规避这类风险; - 它容易和构造函数的
.prototype属性混淆——__proto__是实例身上的属性,.prototype是函数身上的属性,两者用途不同;Object.getPrototypeOf()不会让人产生这种混淆。
替代方案已成熟,无需妥协
即使面对老旧运行时(如 IE8),也能安全补丁:
if (typeof Object.getPrototypeOf === 'undefined') {
Object.getPrototypeOf = function(obj) {
if (obj == null || (typeof obj !== 'object' && typeof obj !== 'function')) {
throw new TypeError('not an object');
}
return obj.__proto__;
};
}
这段代码只在真正缺失时才启用 __proto__,既保持新环境的标准行为,又兜住旧环境,不牺牲可维护性。











