如果它是块(IIUC)中的最后一个表达式,JavaScript将仅优化为非递归循环的递归步骤。这是否意味着右手递归调用将被优化,左手递归调用将不会在下面?
function fibonacci(n) {
if(n < 2) return n;
return fibonacci(n-1) + fibonacci(n-2);
}
答案 0 :(得分:3)
这是否意味着右手递归调用将被优化,左手递归调用将不会在下面?
我不这么认为。只有在您直接返回其他函数返回的内容时才可以使用TCO。由于您的函数在返回结果之前处理这两个结果,因此这两个调用都不能进行尾部优化。
就基于堆栈的机器而言,代码如下:
function fun1()
return fun2(42)
function fun2(arg)
return arg + 1
已翻译为此
fun1:
push 42
call fun2
result = pop
push result
exit
fun2:
arg = pop
arg = arg + 1
push arg
exit
TCO可以消除call-pop-push,而是直接跳转到fun2
:
fun1:
push 42
goto fun2
exit
然而,像你这样的代码片段就是这样:
fun1:
push n - 1
call fun2
result1 = pop
push n - 2
call fun2
result2 = pop
result3 = result1 + result2
push result3
exit
此处,无法使用跳转替换调用,因为我们需要返回fun1来执行添加。
免责声明:这是一个相当理论上的解释,我不知道现代JS编译器如何实际实现TCO。他们非常聪明,所以也许有一种方法可以优化这样的东西。