Object.setPrototypeOf仅修改对象的[[Prototype]],不重置自有属性、内部状态或属性特性;自有属性(含不可枚举、不可写等)完全保留,行为变化仅源于查找路径改变,状态重置需手动处理。

修改原型链后对象的状态不会自动重置,Object.setPrototypeOf 只改变对象的 [[Prototype]],不干预对象自身属性或内部状态。
原型变更不影响已有属性
对象自身的可枚举/不可枚举属性、自有数据属性(包括 value、writable、configurable 等特性)完全保留。例如:
const obj = { a: 1 };
obj.b = 2;
Object.defineProperty(obj, 'c', { value: 3, writable: false });
Object.setPrototypeOf(obj, { d: 4 });
console.log(obj.a); // 1 → 仍在
console.log(obj.b); // 2 → 仍在
console.log(obj.c); // 3 → 仍在(不可写但值未变)
console.log(obj.d); // 4 → 来自新原型
方法调用可能因原型变化而不同
如果原对象或新原型上有同名方法(如 toString、valueOf),调用时会按新原型链查找,行为可能改变:
- 若新原型定义了
toString,obj.toString()将执行新版本 - 若新原型没有该方法,仍沿链向上找,或回退到
Object.prototype.toString - 注意:内置方法(如
Array.prototype.push)对非 Array 对象无效,强行设置原型不会“变成数组”
状态重置需手动处理
所谓“重置”,其实是开发者主动清理,不是 setPrototypeOf 的副作用:
- 删除自有属性:
delete obj.key或Object.keys(obj).forEach(k => delete obj[k]) - 恢复默认属性值:逐个赋值,或用工厂函数重建
- 清空私有状态(如闭包变量、WeakMap缓存)需额外设计,无法靠改原型实现
替代方案更安全可控
频繁修改原型易引发隐性 bug,建议优先考虑:
- 用
Object.create(proto)创建新对象,初始状态干净 - 组合优于继承:把共用逻辑封装成函数或工具对象,通过属性委托而非原型链调用
- ES6 class 继承中,应通过构造函数初始化状态,避免运行时篡改原型


















