__proto__ 是 object.prototype 上的访问器属性,通过 getter/setter 间接操作内部 [[prototype]],而非直接存储原型;现代标准推荐使用 object.getprototypeof、object.setprototypeof 和 object.create 等更规范的 api。

因为 __proto__ 本身不是存储原型对象的“容器”,而是一组内置的 getter/setter 函数,它背后真正存放原型引用的是对象内部不可直接访问的隐藏属性 [[Prototype]]。
它本质是访问器属性(accessor property)
就像你给对象定义一个带 get 和 set 的属性一样,__proto__ 是从 Object.prototype 继承来的访问器属性,其描述符长这样:
- configurable: true —— 可以被删除或重新定义
-
enumerable: false —— 不会出现在
for...in中 -
get() —— 调用时返回当前对象的
[[Prototype]]值 -
set() —— 赋值时实际修改的是
[[Prototype]]的指向
__proto__ 不等于 [[Prototype]]
你可以把它理解成一扇“门”:门本身不是房间,但通过它能进出门后的房间(即 [[Prototype]])。例如:
-
obj.__proto__实际触发 getter,读取[[Prototype]] -
obj.__proto__ = null实际触发 setter,把[[Prototype]]设为null - 删掉
__proto__(如delete Object.prototype.__proto__)后,obj.__proto__会变成undefined,但Object.getPrototypeOf(obj)仍能读到原型 —— 因为底层[[Prototype]]还在,只是“门”没了
现代标准推荐绕过这扇门
ES5 起就提供了更规范、更可控的替代方式:
-
Object.getPrototypeOf(obj)—— 安全读取[[Prototype]] -
Object.setPrototypeOf(obj, proto)—— 显式设置,且有严格限制(比如不能设为非对象) -
Object.create(proto)—— 创建时指定原型,避免运行时修改
这些 API 直接操作 [[Prototype]],不依赖访问器逻辑,也更利于引擎优化和调试。











