Object.setPrototypeOf 可实时修改对象的 [[Prototype]],影响继承行为;语法为 Object.setPrototypeOf(obj, prototype),成功返回 obj,失败抛 TypeError;慎用,因会破坏性能与原型链完整性。

Object.setPrototypeOf 方法可以实时修改对象的内部 [[Prototype]](即物理原型),但需谨慎使用——它会改变对象真实的原型链,影响所有依赖该链的继承行为(如属性查找、instanceof 判断、super 调用等)。
基本用法:替换原型对象
语法为 Object.setPrototypeOf(obj, prototype),其中 obj 是目标对象,prototype 是新原型(可以是另一个对象、函数的 prototype,或 null)。
- 成功时返回修改后的
obj;失败(如obj不可扩展且新原型不匹配)则抛出TypeError - 若
prototype为null,对象将脱离原型链,obj.toString()等原生方法会报错(因找不到Object.prototype上的方法) - 示例:
const obj = { x: 1 };
const newProto = { y: 2, log() { console.log(this.x, this.y); } };
Object.setPrototypeOf(obj, newProto);
obj.log(); // 输出:1 2
与 __proto__ 的区别和注意事项
obj.__proto__ 是非标准但广泛支持的访问器属性,赋值(如 obj.__proto__ = newProto)在效果上等价于 Object.setPrototypeOf(obj, newProto),但:
-
Object.setPrototypeOf是标准、明确的 API,推荐用于生产环境 - 直接操作
__proto__在严格模式下可能被禁用,且某些引擎(如 V8)对其优化较差 - 两者都会触发原型链重绑定,导致 JS 引擎可能失效内联缓存(IC),显著降低性能,尤其在高频调用场景中
实际适用场景(有限但关键)
动态改原型不是常规开发手段,典型适用情况包括:
-
测试模拟:临时让一个对象“假装”继承某构造函数,验证
instanceof或方法继承逻辑 - 框架底层实现:如某些响应式系统(Vue 2 的观测机制)需在创建后统一挂载原型方法
- 兼容旧环境的 polyfill:当无法控制对象创建过程,又需统一注入原型行为时
- 不适用于:频繁更新、性能敏感路径、或替代组合/类继承的设计
替代方案优先考虑
多数需求可通过更安全、高效的方式达成:
- 创建时指定原型:
Object.create(proto)或构造函数 +new - 混入方法:
Object.assign(obj, methods)直接添加自有属性 - 代理封装:
new Proxy(obj, handler)拦截读取,按需委托到不同原型 - ES6 类继承:通过
extends明确声明关系,避免运行时修补

















