JavaScript原型链查找严格按[[Prototype]]链单向回溯:先查对象自身属性,未找到则逐级访问__proto__直至null,不可跳过或干预,仅受原型对象内容与结构控制。

JavaScript 中原型链控制属性与方法的向上查找,核心在于引擎按固定顺序沿着 [[Prototype]] 链(通常通过 __proto__ 或 Object.getPrototypeOf() 访问)逐级回溯,而不是“跳转”或“随机匹配”。这个过程是隐式、自动且不可跳过的。
查找起点:先查自身,不进原型
每次访问 obj.x 或调用 obj.fn(),JS 引擎第一步永远只检查 obj 自身是否拥有该属性(即自有属性)。这包括:
- 直接赋值定义的属性,如
obj.x = 1 - 使用
Object.defineProperty添加的属性(无论是否可枚举) - 构造函数中通过
this.x = ...初始化的属性
只要存在,就立即返回,不再继续向上找。哪怕原型链上也有同名属性,也会被屏蔽。
向上路径:严格按 __proto__ 链单向推进
如果自身没找到,引擎不会“跨链”或“并行搜索”,而是严格遵循一条线性路径:
- 查
obj.__proto__(即Object.getPrototypeOf(obj)) - 若还没找到,再查
obj.__proto__.__proto__ - 接着查
obj.__proto__.__proto__.__proto__…… - 直到某一级对象有该属性,或抵达
Object.prototype.__proto__ === null终止
例如:const arr = [1, 2]; arr.push(3) 中,push 不在 arr 自身,也不在 Array.prototype 的上一级(Object.prototype),而是在 Array.prototype 上——所以查找在第二层就结束。
控制权在原型对象本身,不在查找动作
开发者不能在查找时动态干预路径,但能通过以下方式间接控制“哪里能被找到”:
- 在构造函数的
prototype上添加方法,让所有实例共享且可被查到 - 用
Object.setPrototypeOf(obj, newProto)动态更换某对象的__proto__,改变其后续查找起点 - 用
Object.create(null)创建无原型对象,切断查找链(此时连toString都不可用) - 避免在原型上修改可变对象(如数组、对象字面量),防止意外影响所有继承者
注意:hasOwnProperty、Object.keys 等方法只看自身,完全不走原型链;而 for...in 会遍历整个可枚举链,这是行为差异的关键来源。
常见干扰点:别混淆 prototype 和 __proto__
二者作用域不同,不能混用:
-
Function.prototype是函数对象的原型,决定它自己能调用哪些方法(如bind) -
Function.prototype同时也是该函数作为构造函数时,其实例的__proto__指向目标 - 普通对象(如
{}、new Date())没有prototype属性,只有__proto__ - 箭头函数没有
prototype,也不能用new,因此不参与原型链继承逻辑
真正驱动向上查找的是每个对象内部的 [[Prototype]],而 __proto__ 是它的可访问接口;prototype 只是函数用来“设置别人原型”的工具属性。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











