ECMAScript中__proto__经历从非标准事实属性到被规范容忍、标记为遗留、最终边缘化的过程,ES5引入Object.getPrototypeOf等标准API,ES2015仅限字面量兼容,后续持续弱化,当前已事实废弃。

ECMAScript 规范中 __proto__ 的“去标准化”与标准替代 API(如 Object.getPrototypeOf、Object.setPrototypeOf、Object.create)的逐步确立,是一条贯穿 ES5 到 ES2015+ 的清晰演进线索。它本质不是突然删除,而是从非标准事实属性 → 被规范“容忍但不鼓励” → 明确标记为遗留 → 最终在严格模式和新特性中彻底边缘化。
ES5:__proto__ 首次被“半承认”,但已埋下替代方案伏笔
ES5(2009)本身并未将 __proto__ 写入规范正文,但它在附录 B(可选的规范性附录)中明确指出:__proto__ 是某些实现(主要是 Firefox 和 WebKit)广泛支持的“传统扩展”,浏览器可选择实现,但不强制要求。这意味着:
- 它不是语言标准的一部分,仅是事实上的兼容性妥协;
- ES5 同时正式引入了真正标准的替代方案:
Object.getPrototypeOf(obj)(获取原型)、Object.setPrototypeOf(obj, proto)(设置原型)、Object.create(proto, properties)(基于指定原型创建对象); - 这些新 API 设计更安全、语义更清晰,且不依赖特殊属性名,为后续淘汰
__proto__奠定基础。
ES6/ES2015:__proto__ 被降级为“仅限字面量语法”,标准 API 成为主流
ES2015 正式将 __proto__ 收入规范,但仅限于对象字面量中的简写形式(如 { __proto__: Foo.prototype }),且明确标注为“**仅用于向后兼容**”。更重要的是:
- 类(
class)语法完全屏蔽了__proto__,其原型链由extends和内部机制自动管理; -
Object.setPrototypeOf和Object.getPrototypeOf成为操作原型链的唯一推荐方式,所有现代教程、框架源码(如 Vue 3、React 内部)均采用; - 严格模式下对
__proto__的赋值会静默失败(不报错但无效),进一步削弱其实用性。
ES2015 及之后:规范持续弱化 __proto__,强化标准路径
从 ES2016 开始,TC39 不再为 __proto__ 增加任何新能力,反而通过多个层面收窄其存在空间:
- Proxy 的
getPrototypeOf/setPrototypeOftrap 直接对接标准 API,绕过__proto__; - Reflect API(ES2015 引入)提供
Reflect.getPrototypeOf()和Reflect.setPrototypeOf(),语义更纯粹,且与 Proxy 配合更自然; - MDN、V8 官方文档、TypeScript 类型检查均将
__proto__标记为“不推荐(deprecated)”,警告其性能开销大、行为不可预测(如影响 JIT 优化); - 主流构建工具(Webpack、Vite)和 Linter(ESLint 的
no-proto规则)默认禁用__proto__,强制使用Object.getPrototypeOf等。
当前状态(ES2025):事实废弃,仅存于旧环境兼容层
截至 ES2025 规范草案,__proto__ 已无任何新增描述,其全部定义仍停留在 ES2015 的“附录 B 兼容性条款”中。现代引擎(V8、SpiderMonkey)虽仍保留支持以兼容存量网页,但:
- 新代码生成(如 Babel 输出)完全不使用它;
- Web 平台测试套件(Web Platform Tests)不再为其编写新用例;
- TC39 议程中已无任何关于恢复或增强
__proto__的提案,共识是“保持现状直至自然消亡”。


















