尾调用优化使满足条件的函数调用不新增栈帧,避免栈溢出并提升递归效率;尾调用指函数最后一步直接返回另一函数调用结果,无后续操作。
尾调用优化(Tail Call Optimization,TCO)是JavaScript中一种编译器/引擎级别的性能优化机制,它让**满足尾调用条件的函数调用不增加新的调用栈帧**,从而避免栈溢出、降低内存开销,并显著提升深度递归的执行效率。
尾调用是指函数的**最后一步操作是调用另一个函数(包括自身),且该调用的返回值直接作为当前函数的返回值**。关键在于:没有后续计算、不依赖当前函数的局部变量或执行上下文。
✅ 正确的尾调用示例:
function factorial(n, acc = 1) {
if (n <= 1) return acc;
return factorial(n - 1, n * acc); // 最后一步是调用自身,无额外运算
}❌ 非尾调用示例:
function factorial(n) {
if (n <= 1) return 1;
return n * factorial(n - 1); // 调用后还要做乘法,不是尾调用
}普通递归每调用一次就压入一个栈帧,深度过大时触发“Maximum call stack size exceeded”错误;而启用TCO后,引擎可复用当前栈帧,将递归转化为类似循环的迭代执行。
ES2015(ES6)在规范中定义了严格模式下的尾调用优化,但主流浏览器引擎并未普遍启用:
因此,不能依赖运行时自动TCO。可靠做法是:
稳妥)@babel/plugin-transform-tail-recursion)进行编译时转换"use strict";),这是TCO的前提条件把尾递归函数转为显式循环,保持逻辑清晰且100%兼容:
function factorial(n, acc = 1) {
"use strict";
while (n > 1) {
acc = n * acc;
n = n - 1;
}
return acc;
}这样既保留了尾递归的逻辑结构,又绕过了引擎限制,性能与内存表现都接近理想TCO效果。