如果我可以 tco 命名递归函数,那么应该有一种方法可以 tco 匿名递归函数。如果有办法,请在下面解释如何执行此操作,这是我的递归函数和 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;
}
}
}
最佳答案
尾调用优化
ES6 提议对尾调用系统进行更改,这是一种引擎优化。尾调用是指一个函数作为另一个函数的最后一条语句被调用,如下所示:
function doSomething() {
return doSomethingElse(); // tail call
}
ECMAScript 6 旨在减少严格模式下某些尾调用的调用堆栈大小。通过此优化,不会为尾调用创建新的堆栈帧,只要满足以下条件,就会清除并重新使用当前堆栈帧:
- 必须开启严格模式。
- 尾调用不需要访问当前堆栈帧中的变量(意味着该函数不是闭包)。
- 进行尾调用的函数在尾调用返回后没有进一步的工作要做。
- 尾调用的结果作为函数值返回。
Perhaps the hardest situation to avoid is in using closures. Because a closure has access to variables in the containing scope, tail call optimization may be turned off. For example:
"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 的一本很棒书,Understanding ECMAScript 6。
关于javascript - 我如何在 ES5 中的递归匿名函数上应用 TO(尾调用优化),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39562817/