javascript动态属性查找本质是自下而上的确定性寻址:先查对象自身,无则沿[[prototype]]逐级向上直到null;方法共享靠内存地址共用,实例属性可遮蔽原型。

JavaScript 的动态属性查找,本质就是沿着原型链一级一级“往上问”的过程。它不预设结果,也不跳步,每次访问属性(比如 obj.name 或 obj.toString())都从对象自己开始,找不到就顺着 __proto__ 指针去上一级原型里找,直到找到或走到 null 为止。
查找永远从自身出发
引擎不会跳过对象自己直接去原型上翻。哪怕原型上有同名属性,只要对象自身有,就立刻返回它的值——这保证了实例属性能覆盖原型上的默认行为。
- 例如: const person = { name: 'Alice' };,person.name 直接取自身值,不会去 Object.prototype 查
- 再如: 如果 person.toString 未定义,引擎才顺着 person.__proto__ → Object.prototype 找到那个内置方法
原型链是一条单向、确定的指针路径
每个对象的 [[Prototype]](通常通过 __proto__ 访问)只指向一个地方,且这条路径是构造时就定死的。数组指向 Array.prototype,函数指向 Function.prototype,普通对象指向 Object.prototype,而 Object.prototype.__proto__ === null 是终点。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 关键点: 不是“多个地方同时查”,而是严格按 obj → obj.__proto__ → obj.__proto__.__proto__ → … → null 的顺序推进
- 常见结构: [] → Array.prototype → Object.prototype → null;function(){} → Function.prototype → Object.prototype → null
方法共享靠的是内存地址共用,不是复制
定义在原型上的方法(如 Array.prototype.push),在内存中只存一份。所有实例通过原型链“看到”的是同一个函数引用,所以 arr1.push === arr2.push 为 true。这也意味着:改原型上的方法,所有已有实例立刻受影响。
- 好处: 节省内存,避免重复创建相同逻辑的函数对象
- 注意: 这种共享只适用于原型上的属性/方法,不适用于实例自身添加的同名属性(会屏蔽原型上的)
undefined 是查不到的自然结果,不是错误
当属性在自身和整条原型链上都不存在时,查找过程走到 null 就停止,返回 undefined。这不是异常,而是机制设计的一部分,也是 in 操作符、hasOwnProperty 和单纯点访问之间区别的根源。
- 举例: obj.nonexistent 返回 undefined;'nonexistent' in obj 是 false;obj.hasOwnProperty('nonexistent') 也是 false
- 提示: 判断属性是否存在,要根据场景选对方式——点访问看“能否取到值”,in 看“是否在整条链上”,hasOwnProperty 看“是否在自己身上”
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










