尾調用
尾調用是指函數作爲另一個函數的最後一條語句被調用
function doA(){
return doB();
}
在es5中,尾調用的實現是創建一個新的stack frame,將其推入調用棧中表示函數調用。所以,每一個未用完的 stack frame 都會保存在內存中,當調用棧變得特別大,程序就不好了
ESMAScript 6 尾調用優化
es6 嚴格模式下(非嚴格模式不受影響),滿足一下三個條件,尾調用不再創建新的stack frame ,而是重用當前 stack frame
- 函數不是一個閉包
- 在函數內部,尾調用是最後一條語句
尾調用的結果作爲函數值返回
'use strict'; function doA(){ //優化後 return doB(); }
以下情況是不會優化的
'use strict';
function doA(){
//沒有作爲函數值返回,不會優化
doB();
}
'use strict';
function doA(){
var res = 1;
//func調用了另一個函數作用域內變量,func是閉包,不會優化
func = () => res;
return func();
}
'use strict';
function doA(){
//在返回結果前+1,不會優化
return 1 + doB();
}
'use strict';
function doA(){
//調用不在尾部,無法優化
let res = doB();
return res;
}
利用尾調用優化
尾調用的優化發生在引擎背後,除非是要優化一個函數,否則不必考慮。
遞歸函數是最主要應用的場景。如果遞歸函數的計算量足夠大,尾調用優化可以大大提升程序性能
function factorial(n) {
if( n <= 1 ) {
return 1;
} else {
//無法優化,必須在執行返回結果後進行乘法
return n * factorial(n-1);
}
優化後
function factorial(n, p = 1) {
if( n <= 1 ) {
return 1 * p;
} else {
let res = n * p;
return factorial(n - 1, res);
}
本文摘於 《深入理解es6》密碼:e2y2