__proto__ 是对象原型链的第一跳路径,直接暴露内部[[Prototype]]属性;它可读写但非标准,推荐用Object.getPrototypeOf/setPrototypeOf替代。

__proto__ 不是“语法糖”,而是 JavaScript 引擎内部属性 [[Prototype]] 的可访问入口——它直接暴露了对象在原型链中向上查找的**第一跳路径**。
__proto__ 是什么:对象通往原型的单向桥
每个普通对象(除 null 和 undefined)都有一个 __proto__ 属性,它的值是一个对象(即该对象的原型),指向创建它的构造函数的 prototype 对象。
-
const obj = {}→obj.__proto__ === Object.prototype -
function Cat() {},const miao = new Cat()→miao.__proto__ === Cat.prototype -
Cat.prototype.__proto__ === Object.prototype(因为Cat.prototype是普通对象)
为什么说它是“捷径”:绕过构造函数,直查原型引用
相比 Object.getPrototypeOf(obj) 这个标准方法,__proto__ 允许你用点号语法快速读取或(谨慎)设置原型链接,省去函数调用开销。
- 读取快:
obj.__proto__.toString比Object.getPrototypeOf(obj).toString更简洁直观 - 设置可行但危险:
obj.__proto__ = otherProto能立即改变查找起点(现代引擎支持,但会触发内部优化失效) - 它不依赖构造函数是否存在——哪怕对象是
Object.create(null)创建的,只要不是 null,__proto__就能告诉你它当前连向哪里
捷径 ≠ 推荐路径:它为什么被标记为“非标准、已废弃”
尽管 __proto__ 在所有主流引擎中都可用,但它从未被写入 ECMAScript 标准规范,而是作为历史兼容特性保留。官方明确推荐使用标准替代方案:
- 获取原型:用
Object.getPrototypeOf(obj)(安全、不可枚举、符合规范) - 设置原型:用
Object.setPrototypeOf(obj, proto)或更优的Object.create(proto) - 判断原型关系:用
obj instanceof Constructor或proto.isPrototypeOf(obj)
真正理解“捷径”的关键:它只负责第一环,不构建整条链
__proto__ 本身不执行查找逻辑,也不遍历整条链——它只是返回“下一个该找谁”。真正的属性查找行为由 JavaScript 引擎自动完成:每次访问 obj.prop,引擎内部就顺着 obj.__proto__ → __proto__.__proto__ → … → null 逐级检查,直到命中或终止。
- 所以
obj.__proto__是链的“起始指针”,不是“查找引擎” - 修改它,等于重设整个查找路径的出发点,影响所有后续继承行为
- 这也是为什么随意赋值
__proto__容易引发性能下降或意外覆盖(比如把Array.prototype换成一个空对象,数组方法全失效)

















