圖解尾調用優化

圖解尾調用優化

尾調用

啥是尾調用?html

尾調用就是函數的最後一個步驟調用另外一個函數異步

比方說:函數

20190307171547.png

函數在調用的時候會在調用棧中 push 一個調用幀,每次執行完函數都會逐一彈出調用幀知道全部函數執行完畢,調用棧被清空:oop

調用棧中的同步代碼post

function f1() { console.log('🍎') }
function f2() { f1() }
function f3() { f2() }

f3()

調用棧以下圖:優化

  • 首先執行 script ,將 main 主程序推入調用棧中並執行,發現須要調用 f3
  • 將 f3 函數推入調用棧中,執行 f3,發現須要調用 f2
  • 將 f2 函數推入調用棧中,執行 f2, 發現須要調用 f1
  • 將 f1 推入調用棧中,執行 f1,發現須要調用 console.log 方法
  • 推入 console.log 並打印結果執行完畢
  • 彈出 consoole.log
  • 彈出 f1
  • 彈出 f2
  • 彈出 f3
  • 彈出 main,代碼執行完畢

調用棧中的異步代碼spa

以 setTimeout 爲例:code

console.log('1')
setTimeout(function() {
    console.log('3)
}, 5000)
console.log('2')

調用棧見下圖:htm

  • 執行代碼推入 script 代碼 main 並執行,發現須要執行 console.log
  • 將 console.log 推入調用棧
  • 執行 console.log 打印 1 彈出調用棧
  • 發現 setTimeout 將等待執行的回調函數推入宏任務列表,將 setTimeout 彈出調用棧
  • 繼續執行代碼發現須要執行 console.log 將任務推入調用棧
  • 執行 console.log 打印 2 並彈出調用棧
  • script 代碼 main 執行完畢,彈出調用棧
  • 同步代碼執行完畢,查看宏任務列表發現須要執行 console.log
  • 延遲 5s 將 console.log 推入調用棧
  • 執行 console.log 並打印 2
  • 最後將 console.log 彈出調用棧,代碼執行完畢

尾調用優化

每次在函數被調用的時候,內存都會保存調用幀。尾調用由於是函數的最後一步,所以並不須要外層函數的調用幀。咱們只須要將最後須要執行另一個函數以前用 return 操做符顯式代表"再也不須要此函數"便可blog

20190309013011.png

before

20190309013038.png

after

注意必須使用嚴格模式

在執行過程當中,調用棧的調用幀永遠只有一條,這樣就能夠節省很大一部份內存

參考:

相關文章
相關標籤/搜索