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
「JavaScript学习笔记」 尾递归优化
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
推荐阅读更多精彩内容
- 要知道什么是尾调用,我们就要先从调用栈开始说起。 什么是调用栈 ? 调用栈((Call Stack)是一个基本的计...