原型链属性查找是实时逐级向上搜索,不缓存不拷贝;修改原型属性即时影响所有实例,但替换整个prototype会断开老实例连接。

原型链中对象属性查找的动态性,核心在于“查找是实时的、逐级向上进行的”,不是拷贝,也不是快照——每次访问属性时,引擎都会从当前对象出发,沿着 [[Prototype]] 链一路向上搜索,直到找到或抵达 null。
属性查找永远走链,不缓存结果
JavaScript 不会把查到的属性“复制”到实例上,也不会记住上次在哪一层找到的。每次调用 obj.method() 或读取 obj.prop,都重新执行一次完整查找:
- 先查
obj自身有没有该属性(自有属性) - 没有就查
obj.__proto__(即Object.getPrototypeOf(obj)) - 还没找到,就继续查
obj.__proto__.__proto__,依此类推 - 最终停在
Object.prototype,它的[[Prototype]]是null
修改原型,所有已有实例立刻可见
因为实例和原型之间只是指针关联([[Prototype]] 指向一个对象),不是深拷贝或绑定快照。只要原型对象本身被添加、删除或改写属性,所有指向它的实例都会同步感知:
Person.prototype.sayHi = function() { console.log('hi') };- 哪怕
const p = new Person()在这行之前就创建好了,p.sayHi()依然能正常运行 - 同理,后续删掉
Person.prototype.sayHi,p.sayHi就变成undefined
重写整个 prototype 会断开已有实例的连接
动态性只适用于对原型对象的“增删改属性”,不适用于“替换整个原型对象”:
- 构造函数首次被调用时,实例的
[[Prototype]]被固定指向当时的Person.prototype - 之后执行
Person.prototype = { sayName() { ... } };,只是让新实例指向新对象;老实例仍连着旧原型 - 所以老实例无法访问新原型上的方法,也不会受新原型上
constructor等属性影响
常见误区:__proto__ 和 prototype 不是同一个东西
理解动态性的前提,是分清这两个关键角色:
-
Person.prototype是函数独有的属性,定义“将来 new 出来的对象该连向谁” -
obj.__proto__是对象(实例)身上的内部链接,实际指向的就是它诞生时Person.prototype的值 - 修改
Person.prototype不会影响已存在obj.__proto__的指向;但修改Person.prototype.xxx会反映在所有共享它的obj.__proto__上
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











