如何在ES5中对recursion匿名函数应用TCO(尾调用优化)

如果我可以通过一个名为recursion函数的tco,应该有一种方法来让tco匿名recursion函数。如果有一种方法,请解释下面如何做到这一点是我的recursion函数和TCO函数。

function recursive(length, callback) { tco((function (i, sum) { var args = arguments; if (i > length) { console.log("break statement"); callback(sum) return sum } else { return args.callee(i + 1, sum + i) } }))(0, 0) } function tco(f) { var value; var active = false; var accumulated = []; return function accumulator() { accumulated.push(arguments); if (!active) { active = true; while (accumulated.length) { value = f.apply(this, accumulated.shift()); } active = false; return value; } } } 

尾巴呼叫优化

ES6build议对尾部呼叫系统进行更改,引擎优化。 尾部调用是函数被调用为另一个函数中的最后一个语句,如下所示:

 function doSomething() { return doSomethingElse(); // tail call } 

ECMAScript 6试图在严格模式下减less某些尾部调用的调用栈大小。 通过这种优化, 不必为尾部调用创build新的堆栈帧,只要满足以下条件,当前堆栈帧就被清除并重新使用

  1. 严格模式必须打开。
  2. 尾部调用不需要访问当前栈帧中的variables(意思是函数不是闭包)。
  3. 尾部呼叫返回后,尾部呼叫的function不再需要进行。
  4. 尾部调用的结果作为函数值返回。

也许最难避免的情况是使用闭包。 因为闭包可以访问包含范围内的variables,所以tail call优化可能被closures。 例如:

 "use strict"; function doSomething() { var num = 1, func = () => num; // not optimized - function is a closure return func(); } 

利用TCO优化:

考虑这个计算因子的函数:

 "use strict"; function factorial(n) { if (n <= 1) { return 1; } else { // not optimized - must multiply after returning return n * factorial(n - 1); } } 

为了优化函数,需要确保在最后一次函数调用之后不会发生乘法运算。

 "use strict"; function factorial(n, p = 1) { if (n <= 1) { return 1 * p; } else { let result = n * p; // optimized return factorial(n - 1, result); } } 

来源:尼古拉斯·扎卡斯(Nicholas Zakas)的一本很棒的书,了解ECMAScript 6。