super()调用带来可测量的初始化开销,而super.xxx是单步限定的受控原型查找,性能瓶颈主要来自继承深度和super()频次,非super.xxx本身。

super 调用和原型查找是 JavaScript 继承中两个密切相关但作用机制不同的环节:前者是显式、主动的控制流委托,后者是隐式、自动的属性访问路径。它们共同影响代码行为,但对性能的影响方式和程度截然不同。
super() 调用带来可测量的初始化开销
每次 new 子类实例时,super() 的执行会触发一系列引擎级检查与上下文绑定,这是性能损耗的主要来源:
- 子类构造函数必须首行调用 super(),V8 需验证 this 是否已激活,并沿 [[Prototype]] 链定位父类 constructor
- 每多一层继承(如 A → B → C),就多一次 super() 调用链,实测显示:单层继承比纯类慢 50%~60%,两层慢 75%~80%,三层及以上呈非线性衰减
- 该开销发生在实例化瞬间,与后续运行无关;若对象创建频次高(如游戏帧循环、大量 DTO 实例),需特别关注
原型查找本身极快,但 super.xxx 有额外约束
普通 this.xxx 查找会沿 __proto__ 链逐层向上,直到找到属性或抵达 null;而 super.xxx 是受控查找,不走完整链:
- super.method() 只在直接父类的 prototype 上查找,不继续向上穿透(例如 C extends B extends A,C 中 super.method() 只查 B.prototype,哪怕 A.prototype 有也不会命中)
- 这种“单步限定”让查找更确定、更快——避免了冗余遍历,但也意味着它不会利用更上层的共享方法,设计时需注意方法放置层级
- 如果父类 prototype 上无目标属性,super.xxx 直接返回 undefined,不 fallback 到 this.xxx 或 Object.prototype,这减少了不确定性,也省去了兜底判断成本
静态方法中的 super 性能独立于实例链
静态上下文里的 super 指向父类构造函数本身(而非其 prototype),查找基于构造函数的 [[Prototype]] 链:
- C.info() 中 super.info() 查找的是 B.info,依赖的是 C.[[Prototype]] === B 这一静态关系,与实例原型链无关
- 该查找发生在方法执行时,但因静态链通常稳定且层级浅,实际开销远低于构造阶段的 super()
- 静态继承链断裂(如手动篡改构造函数 [[Prototype]])会导致 super 失效,但这种情况罕见,一般不影响常规性能
优化建议:减少层数,明确意图
性能瓶颈主要来自继承深度和 super() 频次,而非 super.xxx 本身:
- 优先考虑组合替代深层继承(如用字段委托代替多层 extends),尤其在高频创建场景
- 若必须多层继承,确保每一层 constructor 都正确调用 super() —— 漏写不仅逻辑错误,还会让初始化提前终止,看似“快”实则功能缺失
- 避免在循环或递归逻辑中误用 super()(如方法内 self-referencing),可能引发栈溢出,这不是性能问题而是运行崩溃
- 对只读场景,可缓存 super.xxx 的结果(如 const parentMethod = super.method.bind(this)),但注意 bind 开销是否值得











