object.setprototypeof修改的是对象自身的[[prototype]]内部槽,即__proto__指向的原型对象,而非构造函数的prototype属性;它仅重定向原型查找起点,不复制属性、不影响构造过程,但会破坏v8内联缓存导致性能下降。

Object.setPrototypeOf 直接修改对象的内部 [[Prototype]](即隐式原型),从而改变其继承链。它不复制属性,也不影响构造函数或 prototype 属性本身,只重定向该对象的原型查找起点。
它改的是哪个“原型”?
它修改的是对象自身的 [[Prototype]] 内部槽,也就是通过 obj.__proto__ 可访问、Object.getPrototypeOf(obj) 可读取的那个原型对象。例如:
-
let a = {};→a的[[Prototype]]是Object.prototype -
Object.setPrototypeOf(a, Array.prototype);→ 此后a能直接调用push、map等数组方法(因为查找路径变成了a → Array.prototype → Object.prototype → null)
和构造函数的 prototype 有关系吗?
没有直接关系。构造函数的 prototype 属性只在 new 实例化时被赋给新对象的 [[Prototype]]。而 setPrototypeOf 绕过了构造过程,手动设置任意对象的原型。比如:
-
function Foo() {},Foo.prototype.bar = 'ok'; -
let x = {};,Object.setPrototypeOf(x, Foo.prototype); - 此时
x.bar就是'ok',尽管x根本不是用new Foo()创建的
使用时要注意什么?
这个操作会破坏 V8 等引擎的内联缓存(IC),导致性能下降,尤其在频繁调用的代码中。另外:
- 不能用于
null或原始值(如字符串、数字),会抛错 - 若目标原型是不可扩展对象(
Object.isExtensible === false),且当前对象已有同名自有属性,可能引发意外行为 - 尽量避免在热路径上使用;更推荐用
Object.create(proto)创建带指定原型的新对象
替代方案有哪些?
如果只是想让新对象继承某原型,优先用:
-
Object.create(proto)—— 创建时指定原型,语义清晰且高效 - 类继承(
class B extends A)或构造函数链(B.prototype = Object.create(A.prototype))—— 适合设计阶段的继承建模 - 组合/委托(显式调用
proto.method.call(obj, ...))—— 更可控,避免隐式原型污染











