JavaScript原型链查找是确定性内存寻址:先查对象自身属性,无则沿__proto__单向向上遍历,直至null;所有实例共享原型上的方法,仅存一份内存副本。

JavaScript 原型链查找不是“猜谜”,而是一套确定性的内存寻址流程:先查自己,再顺着指针一级级往上翻,直到找到或走到尽头(null)。
查找从对象自身开始,不跳过也不预判
每次访问一个属性(比如 obj.name 或 obj.toString()),引擎第一件事就是检查该对象的自有属性表——也就是它自己内存空间里有没有这个键。有就直接返回值,整个过程结束;没有才启动向上查找。
这就像翻自己的背包找钥匙:先摸口袋、再看夹层、最后翻内袋;没找到,才去问室友(原型)借一把。
__proto__ 是每个对象自带的“上楼箭头”
除 null 外,所有对象内部都藏着一个隐藏链接 [[Prototype]](开发者常通过 __proto__ 访问)。它不存储数据,只存一个地址——指向它的“上一级模板”。
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
const obj = {}→obj.__proto__ === Object.prototype -
const arr = []→arr.__proto__ === Array.prototype -
function Foo(){}→Foo.__proto__ === Function.prototype
这个指针是对象诞生时就写死的,由构造方式决定,不能靠赋值改变(obj.__proto__ = ... 虽可写但不推荐,应使用 Object.setPrototypeOf())。
查找是单向链式推进,中途不拐弯
引擎沿着 __proto__ 一路向上,每到一个对象就查一次它的自有属性,不跳步、不回溯、不并行搜索:
- 查
person.sayHello():先看person自身 → 没有 → 看person.__proto__(即Person.prototype)→ 有 → 执行 - 查
person.toString():自身无 →Person.prototype无 → 再查Person.prototype.__proto__(即Object.prototype)→ 有 → 执行 - 查
person.nonexistent:自身无 →Person.prototype无 →Object.prototype无 →Object.prototype.__proto__是null→ 停止 → 返回undefined
共享的本质是“共用同一块内存”,不是复制
方法定义在原型上(如 Person.prototype.walk = function(){...}),V8 引擎只在堆中分配一次函数对象,所有实例的 __proto__ 都指向同一个原型对象。所以:
-
person1.walk === person2.walk返回true - 修改
Person.prototype.walk,所有已有实例立即生效 - 不会因为创建 1000 个实例,就生成 1000 份 walk 函数副本
这就是原型链真正解决的问题:用空间换时间,靠引用共享省内存,靠链式查找保灵活性。

















