JavaScript对象字面量中__proto__是已废弃的非标准语法,仅用于浏览器兼容,实际执行的是运行时[[SetPrototypeOf]]操作而非构造时指定原型,应改用Object.create()等标准方法。

JavaScript 中对象字面量里写 __proto__ 不是规范用法,它既不是标准语法,也不该被当作“设置原型的简写”。这种写法属于已废弃的遗留特性,仅保留用于浏览器兼容性,现代开发中应避免使用。
__proto__ 在字面量中只是属性赋值,不是原型声明
当你写:{ __proto__: Parent.prototype, name: 'Alice' }
JavaScript 实际执行的是:先创建一个普通对象(原型默认为 Object.prototype),再把 Parent.prototype 赋给它的 __proto__ 属性——这是一次运行时的 [[SetPrototypeOf]] 操作,而非在构造时指定物理原型。
- 该行为可被代理(Proxy)拦截,也可能触发引擎性能降级
- 在严格模式、ES 模块环境或 Deno 等现代运行时中,可能直接报错
- ECMAScript 规范明确将其列为 Annex B 内容,标注为“仅用于 Web 兼容性”,不鼓励采用
对象字面量本身无法显式指定 [[Prototype]]
标准的对象字面量语法(如 {} 或 { a: 1 })没有提供任何机制来控制新对象的内部 [[Prototype]]。所有这类对象的原型链起点固定为 Object.prototype,这是语言设计决定的默认行为。
- 即使你写了
{ __proto__: null },也只是后续覆盖了__proto__属性,并非创建时就跳过Object.prototype - 想真正绕过
Object.prototype,必须用Object.create(null) - 想让对象继承自某个特定原型,唯一标准方式是
Object.create(proto)
推荐替代方案:清晰、安全、符合标准
需要控制原型链时,应放弃字面量中的 __proto__,改用语义明确的标准方法:
-
Object.create(proto, descriptors):最直接的方式,第一个参数就是你要设为
[[Prototype]]的对象 - class / extends:适用于类式继承场景,底层仍基于原型,但语法更可靠、constructor 自动维护
-
Object.setPrototypeOf(obj, proto):仅在已有对象需动态改原型时使用,明确且可控,比赋值
__proto__更规范
为什么不该依赖字面量里的 __proto__
尽管部分浏览器支持,但它的存在本质是历史包袱:
立即学习“Java免费学习笔记(深入)”;
- 不是语言核心特性,未来版本可能移除
- 破坏 JS 引擎的优化假设(如内联缓存),影响执行效率
- 容易与真正的原型继承混淆,误导初学者认为这是“继承语法”
- 与 TypeScript、Babel、打包工具等协作时可能出现不可预期行为


















