仅初始化阶段调用Object.setPrototypeOf设置原型继承的性能损耗有多大?
你这种仅在初始化阶段执行一次的Object.setPrototypeOf调用,几乎不会产生任何性能问题,后续的对象属性访问也可以正常享受JS引擎的优化。
我们常说的Object.setPrototypeOf的性能危害,核心触发前提是修改已经被JS引擎生成内联缓存、建立形状(Hidden Class/Shape)映射的对象原型:
- 当一个对象的属性被访问过之后,JS引擎会为它生成对应的形状标记,同时把属性查找的结果缓存到内联缓存中,后续访问可以直接命中缓存,跳过完整的原型链遍历。
- 如果这时候你修改了这个对象的
[[Prototype]],已经生成的所有相关缓存都会直接失效,引擎需要重新计算形状、重建缓存,这个过程会产生额外开销,如果频繁修改、或者修改的是被大量引用的热对象,就会导致整体性能大幅下降。
回到你的代码场景:你是在构造函数定义完成后、还没有任何Child实例被创建、也没有任何代码访问过Child.prototype的属性之前,就修改了它的原型。这时候引擎还没有为Child.prototype生成任何优化缓存,修改原型的操作相当于直接给它设置了初始的原型链,和你用Child.prototype = Object.create(Parent.prototype)这种传统继承写法的效果完全一致,后续第一次访问Child实例属性时,引擎会基于最终的原型链生成正常的缓存,不会有任何额外的性能损耗。
甚至这种写法和ES6类继承的底层实现逻辑是一致的:class Child extends Parent的内部本质就是执行了Object.setPrototypeOf(Child.prototype, Parent.prototype),而类继承是JS标准推荐的写法,本身不存在性能问题,核心原因就是原型修改是在类初始化阶段完成的,还没有任何相关的优化缓存生成。
只有在以下场景使用Object.setPrototypeOf才会产生明确的性能问题:
- 运行时反复修改同一个对象的原型
- 修改已经生成过内联缓存的热对象(比如已经被大量实例引用的原型对象、已经被多次访问过的普通对象)的原型
- 在业务代码的热路径中动态修改对象原型
内容的提问来源于stack exchange,提问作者coderboy
相关产品推荐
相关产品推荐

