[譯]輕鬆十步走,帶你領略JS呼叫棧的執行原理

thecodingape發表於2019-01-17

呼叫棧是直譯器(就像瀏覽器中的javascript直譯器)追蹤函式執行流的一種機制。當執行環境中呼叫了多個函式時,通過這種機制,能夠幫助我們追蹤到哪個函式正在執行,執行的函式體中又呼叫了哪個函式。

有關呼叫棧,你需要知道以下幾點:

  • 每呼叫一個函式,直譯器就會把該函式新增進呼叫棧並開始執行。

  • 正在呼叫棧中執行的函式還呼叫了其它函式,那麼新函式也將被新增進呼叫棧,一旦這個函式被呼叫,便會立即執行。

  • 當前函式執行完畢後,直譯器將其清出呼叫棧,繼續執行當前執行環境下的剩餘的程式碼。

  • 當分配的呼叫棧空間被佔滿時,會引發“堆疊溢位”。

舉例

function greeting() {
    // [1] 這裡有程式碼哦~
    sayHi();
    // [2] 這裡也有程式碼哦~
}

function sayHi() {
    return "Hi!";
}

// 呼叫greeting函式
greeting();

// [3] 這裡還有程式碼哦~
複製程式碼

以上程式碼會按照如下方式執行:

  1. 忽略前面所有函式,直到greeting()函式被呼叫。

  2. greeting()新增進呼叫棧列表。

呼叫棧列表
greeting()
  1. 執行greeting()函式體中的所有程式碼。

  2. 程式碼執行到sayHi()時,該函式被呼叫

  3. sayHi()新增進呼叫棧列表

呼叫棧列表
greeting()
sayHI()
  1. 執行sayHi()函式體中的程式碼,直到全部執行完畢。

  2. 返回來繼續執行greeting()函式體中sayHi()後面的程式碼。

  3. 刪除呼叫棧列表中的sayHi()函式。

呼叫棧列表
greeting()
  1. greeting()函式體中的程式碼全部執行完畢,返回到啟用greeting()的程式碼行,繼續執行剩餘JS程式碼。

  2. 刪除呼叫棧列表中的greeting()函式。

呼叫棧列表

一開始,我們得到一個空空如也的呼叫棧。

隨後,每當有函式被呼叫都會自動地新增進呼叫棧,執行完函式體中的程式碼後,呼叫棧又會自動地移除這個函式。

最後,我們又得到了一個空空如也的呼叫棧。

相關文章