Object.getPrototypeOf()是ECMAScript标准定义的只读方法,返回对象的[[Prototype]]内部槽值;__proto__是非标准遗留访问器属性,已弃用;Object.setPrototypeOf()是受约束的原型变更操作,三者职责不同,并无“三角演变关系”。

直接说结论:__proto__、Object.getPrototypeOf()、Object.setPrototypeOf() 并不构成“内存模型上的三角演变关系”——这个说法在 JavaScript 规范和引擎实现中并不存在。它们是不同层级、不同用途、不同语义的工具,混用“三角演变”容易引发概念混淆。
__proto__ 是历史遗留的访问器属性,不是内存指针
它只是 Object.prototype 上一个可读写的 访问器属性(accessor property),内部通过 get/set 函数委托给引擎底层的原型链操作,并非直接暴露内存地址或引用指针。
例如:
-
obj.__proto__实际调用的是引擎内置的[[GetPrototypeOf]]操作 -
obj.__proto__ = x实际触发的是[[SetPrototypeOf]]操作(且受configurable和extensible约束) - 它已被 ES6 标准标记为“deprecated(已弃用)”,仅保留向后兼容,不应在新代码中使用
getPrototypeOf 是安全、只读的规范级查询接口
Object.getPrototypeOf(obj) 是 ECMAScript 规范定义的标准方法,对应内部抽象操作 [[GetPrototypeOf]],作用单一明确:
返回 obj 当前的 [[Prototype]] 内部槽值(即其原型对象),不可写、无副作用、无兼容风险。
- 它不修改任何状态,只做查询
- 对 null/undefined 抛错,对非对象强制转换(如字符串会包装成 String 实例再查)
- 所有现代引擎(V8、SpiderMonkey、JavaScriptCore)都将其优化为常量时间查找
setPrototypeOf 是有代价的、受约束的变更操作
Object.setPrototypeOf(obj, proto) 对应内部操作 [[SetPrototypeOf]],但它不是“设置内存指针”那么简单:
- 引擎需校验:目标
proto是否为 object 或 null;当前对象是否可扩展(extensible);是否已有不可变的 [[Prototype]](如被Object.freeze()锁定) - 若成功,可能触发整个原型链的隐藏类(IC cache)失效,导致后续属性访问性能下降(V8 中尤其明显)
- 它改变的是对象的
[[Prototype]]内部槽,但该槽本身不可枚举、不可配置、不可删除——它是对象元数据的一部分,不是普通属性
三者之间没有“演变”,只有职责分工
所谓“三角”实际是同一底层机制([[Prototype]] 内部槽)在不同抽象层的投影:
-
__proto__→ 面向开发者的历史兼容层(带副作用、易误用) -
Object.getPrototypeOf()→ 面向标准的只读查询层(推荐用于检测、调试、框架逻辑) -
Object.setPrototypeOf()→ 面向高级场景的受控变更层(极少需要,通常可用Object.create(proto)替代)
它们共用同一个引擎底层能力,但彼此不演化、不替代、不升级——就像“门把手”“门锁”“门框”都属于一扇门,但没人说它们构成“三角演变”。

















