修改原型不影响已有实例的自有属性,其仍优先被访问;原型变更仅动态影响未定义在实例上的属性查找,且需注意in操作符与hasownproperty()等行为差异。

修改原型后,已有实例的属性不受影响。实例自身拥有的属性(自有属性)依然存在,访问时优先读取自有属性,不会因为原型改变而丢失或覆盖。
自有属性保持不变
调用 Object.setPrototypeOf(obj, newProto) 只会改变对象的内部 [[Prototype]] 链,不影响对象自身的属性存储。无论原型怎么换,obj.a = 123 这样的赋值始终保留在 obj 上。
- 已有属性仍在对象内部属性表中,和原型无关
- 读取属性时仍按“自身 → 原型链”顺序查找,自有属性永远优先
- 删除自有属性(
delete obj.prop)后,才可能从新原型上读到同名属性
原型上的属性访问会动态响应
修改原型后,对未定义在实例上的属性,访问行为会立即切换到新原型。比如原来原型有 foo(),现在换成一个带 foo() { return 'new' } 的原型,那么 obj.foo() 就会调用新的方法。
- 不重新初始化实例,也不拷贝属性,纯链式查找机制生效
- 如果新原型没有某属性,而旧原型有,那该属性就“不可见”了(除非手动恢复原型链)
- 注意:箭头函数、闭包捕获的 this 不会因原型变更而自动更新
要注意的边界情况
某些操作看似“改属性”,实则依赖原型链,容易出错:
-
in操作符和hasOwnProperty()行为不同:'x' in obj查整条链,obj.hasOwnProperty('x')只查自身 - 解构赋值、展开运算符(
{...obj})只复制自有可枚举属性,不涉及原型 - 使用
Object.create(null)创建的对象没有默认原型,设新原型后才开始有继承行为
替代方案更可控
如果目的是让一批实例“统一升级行为”,比起动态改原型,更推荐:
- 提前设计好可替换的原型对象,避免运行时频繁修改
- 用组合代替继承:把共享逻辑封装成工具对象,实例持有引用
- 需要动态能力时,考虑 Proxy 包装,而非硬切原型











