尾调用优化

94 阅读1分钟

10.13.2 尾调用优化的代码 可以通过把简单的递归函数转换为待优化的代码来加深对尾调用优化的理解。下面是一个通过递归 计算斐波纳契数列的函数: function fib(n) { if (n < 2) { return n; } return fib(n - 1) + fib(n - 2); } console.log(fib(0)); // 0 console.log(fib(1)); // 1 console.log(fib(2)); // 1 console.log(fib(3)); // 2 console.log(fib(4)); // 3 console.log(fib(5)); // 5 console.log(fib(6)); // 8 显然这个函数不符合尾调用优化的条件,因为返回语句中有一个相加的操作。结果,fib(n)的栈 帧数的内存复杂度是 O(2n )。因此,即使这么一个简单的调用也可以给浏览器带来麻烦: fib(1000); 当然,解决这个问题也有不同的策略,比如把递归改写成迭代循环形式。不过,也可以保持递归实 现,但将其重构为满足优化条件的形式。为此可以使用两个嵌套的函数,外部函数作为基础框架,内部 函数执行递归: "use strict"; // 基础框架 function fib(n) { return fibImpl(0, 1, n); } // 执行递归 function fibImpl(a, b, n) { if (n === 0) { return a; } return fibImpl(b, a + b, n - 1); } 这样重构之后,就可以满足尾调用优化的所有条件,再调用 fib(1000)就不会对浏览器造成威胁了。