在程序设计中
每个函数的使用都会在内存中建立与之对应的作用域,并保存其上下文
递归是迭代解决问题的常用方式
而当二者相遇,就可能会链接到Stack Overflow :-)
A:1
2
3
4
5
6
7
8
9function fomatSum(val){
return 'sum / 2 =' + val/2 ;
}
function comp(x,y){
var sum = x + y;
return fomatSum(sum);
}
comp(2,4);
B:
1 | function fomatSum(val){ |
尾调用是通过减少内存使用达到优化目的
A、B两种写法都能得到相同的结果:sum / 2 = 3
在A中,当程序运行到return fomatSum的时候,此时comp函数已经做完了它该做的事情,只需要呼叫comp做接下来的事情。
相当于接力赛,comp把接力棒(传入所需参数)给fomatSum后,comp就可以休息了(释放掉),故 不用保存comp的调用帧 。
在B中,当程序运行到fomatSum函数的时候,就跑去执行fomatSum了,但是需要返回值给result(这时候就需要通过调用帧 回到comp函数中),然后return这个值。
相当于餐馆点餐,服务员comp把菜单(传入所需参数)给厨师fomatSum后,comp还需要等待fomatSum把东西做好,再给顾客上餐,所以需要调用帧去找到服务员comp。
关于深入理解尾调用(tail-call)以及尾递归(tail-recursive),建议配合 上下文 进行理解其目的和意义。