属性查找始终遵循“自身→原型链向上”顺序,重写原型链仅改变查找路径和来源,不阻止查找机制;已创建实例不受影响,新实例基于新原型链查找。

原型链机制下,属性查找和原型链重写不是互斥关系,而是存在明确的优先级与覆盖逻辑——查找行为本身不会被重写阻止,但重写会改变查找结果的来源和路径。
属性查找永远遵循“自身 → 原型链向上”顺序
无论原型是否被重写,JavaScript 引擎访问属性时始终执行相同流程:
- 先检查对象自身是否拥有该属性(包括自有属性、通过
Object.defineProperty添加的、或直接赋值的) - 若无,则沿
__proto__(即Object.getPrototypeOf())逐级向上查找 - 查找终点是
Object.prototype,再往上为null,返回undefined
这个过程不可跳过、不可绕开,也不因原型被重写而失效。重写只是改变了某一级原型的内容或结构,而非禁用查找机制。
原型链重写会切断原有连接,导致查找路径变更
所谓“重写原型链”,常见于以下操作,它们直接影响后续查找的起点和内容:
立即学习“Java免费学习笔记(深入)”;
-
Constructor.prototype = new OtherConstructor():替换整个原型对象,原prototype上的方法/属性对新实例不可见 -
Object.setPrototypeOf(obj, newProto):直接修改实例的__proto__,使其跳过原有原型,指向新对象 -
obj.__proto__ = newProto(不推荐):效果同上,但可能引发性能问题 -
Object.create(null)创建的对象没有Object.prototype作为末端,查找提前终止
注意:重写后,**已创建的实例不受影响**(除非显式改其 __proto__),但**新实例将基于新原型链查找**。
同名属性屏蔽(Shadowing)是关键冲突点
当实例自身添加与原型链上同名的属性时,查找立即终止于该实例层,不再继续向上——这不是互斥,而是设计机制:
-
person.name = 'Alice'后,即使Person.prototype.name = 'default',person.name仍返回'Alice' - 删除实例属性:
delete person.name,再次访问就会恢复从原型链查找 - 重写原型上的属性(如
Person.prototype.greet = newFn)会立即影响所有未屏蔽该属性的实例
这种屏蔽关系让“重写原型”和“实例赋值”形成事实上的优先级竞争,但本质仍是查找规则的自然体现。
class 语法糖下的隐式重写风险
使用 class 定义时,若手动重写 constructor.prototype,会破坏 instanceof 和构造器识别:
-
class A {}默认A.prototype.constructor === A - 若执行
A.prototype = { method() {} },则new A() instanceof A返回false,且constructor指向Object - 正确做法是补充
A.prototype.constructor = A,或用Object.assign(A.prototype, {...})避免全量替换
这类重写不阻止属性查找,但会让继承关系失真,间接影响开发调试和类型判断。


















