修改原型链本身(如替换整个prototype)不影响已存在实例,但修改现有原型上的属性或方法会实时反映到未遮蔽的实例上;遮蔽、冻结、无原型对象等会导致查找提前终止。

修改原型链本身(比如替换整个 prototype 对象)不会影响已存在的实例;但修改现有原型对象上的属性或方法,只要未被遮蔽,就会实时反映到所有已实例化对象上。
修改 prototype 对象本身:不影响旧实例
当你用赋值方式重写整个构造函数的 prototype,例如:
Person.prototype = { sayHi() { console.log('Hi!'); } };
这个操作只会影响之后用 new Person() 创建的新实例。所有此前创建的实例,其内部 [[Prototype]] 仍指向原来的原型对象,不会自动切换过去。
也就是说:重写 prototype 是“断连”操作,不是“刷新”操作。
修改现有原型上的属性/方法:旧实例立即生效
只要不重写 prototype,而是直接在它上面增、删、改,比如:
Person.prototype.getName = function() { return this.name; };Person.prototype.age = 25;delete Person.prototype.sayHello;
这些改动会立刻对所有已创建和将创建的实例生效——前提是它们没有自己定义同名属性(即未发生遮蔽)。
例如:person1.age = 30 后,再设 Person.prototype.age = 25,person1.age 仍是 30,因为自有属性优先级高于原型查找。
引用类型属性的共享特性需特别注意
如果原型上定义的是引用类型(如数组、对象),所有实例默认共享同一份内存:
Person.prototype.colors = ['red', 'blue'];
此时若执行 person1.colors.push('green'),person2.colors 也会变成 ['red', 'blue', 'green']。
要避免意外共享,可在构造函数中为每个实例初始化独立副本:
function Person() { this.colors = ['red', 'blue']; }
哪些情况会让原型修改“失效”
- 实例自身已有同名属性或方法(遮蔽)
- 方法被
bind()、call()或箭头函数固化了上下文,不再走原型查找 - 原型对象被
Object.freeze()或Object.seal()锁定 - 使用了
Object.create(null)创建的对象,没有原型链
这些都不是“修改没起作用”,而是属性访问路径被提前终止或阻断了。











