function tail(fn) {
var value,
active = false,
stack = []
return function() {
// 接受调用栈参数
stack.push(arguments)
// 控制被包装的函数开始执行时使用下面的逻辑
if (!active) {
active = true
while (stack.length) {
// 当fn.apply 执行后,将接受的参数丢给实际要执行逻辑的函数
// 如果其中还是调用了被优化的具名方法,比如下面的factorial
// 那么当执行其中的方法时,由于所有Factorial共享一个active,递归失败,参数传给stack
// 因此该方法执行时,如果还有factorial执行,则只会把参数都给stack
// 此时length增加,while循环继续
value = fn.apply(this, stack.shift())
// 由此,可以发现只有刚开始调用的方法会循环执行,递归调用的方法,只会把参数传给stack,再拿出来给原始函数调用
// 最后,当不再调用递归时,while结束
}
active = false
// 返回最后的value
return value
// 需要注意的是,如果不是尾调递归,不能这样包装使用
}
}
}
// 将实际执行的函数用tail方法包装
var factorial = tail((total, n) => {
return n === 1
? total
: factorial(n * total, n - 1);
});
factorial(1, 5); // 120
reference
ES6中的尾调优化及其他相关的优化算法
网友评论