之前文章提到JavaScript引擎主要執行程式碼的地方是call stack,而且更精準地說應該是call stack裡的execution context(如下圖),今天就來複習execution context。
Excution Context
Execution context(中文應該是「執行環境」)是一個抽象的名詞,描述JavaScript在執行程式碼的環境(environment),這個執行環境會包含所有跟程式碼執行有關的東西,像是變數、函式引數等等,先來談一下execution context究竟會有哪些東西。
一般的execution context會有以下資訊:
- Variable environment
- var, let, const variables
- functions
- argument objects
- Scope chain
- this keyword
要注意的是,箭頭函式(arrow function)沒有其中的argument objects和this keyword。
因為這些資訊幾乎都可以當作一篇主題文章來寫,今天就只先專注在call stack 如何決定執行順序以及execution context的概念。
Call Stack: How to Wroks?
當程式碼經過即時編譯(just-in-time compilation)後,會在引擎中call stack準備執行,程式碼的執行步驟大致如下:
- 建立全域執行環境(global execution context)
- 執行全域執行環境的程式碼
- 建立函式執行環境並執行程式碼
簡單說明一下上述步驟,首先會有一個全域執行環境(global execution context)產生,此時函式以外的程式碼(稱為 top-level code)會被"掃過"一遍,其中的變數、函式定義、函式引數就會被儲存在variable environment object,同時也會產生scope chain和this keyword(後面兩者會留待之後的文章說明),總之至少知道包含函式定義的變數們都會被記住。
接著就是開始執行全域執行環境的程式碼,如果當中碰到有函式被呼叫(called)的情況,此時會建立這個函式的執行環境並執行函式裡的程式碼。
至於JavaScript引擎是怎麼決定什麼時候要執行哪個執行環境,這就得仰賴call stack。
Call stack的stack(中文稱「堆疊」)是一種資料結構,其資料儲存在stack裡面會採用先進後出(first-in last-out)的方式來處理。Stack就好比一疊文件,最先放進的文件會因為上面堆疊著後來才放上去的文件,得等到上面文件都被處理過才能處理最一開始放進去的文件。
如圖所示,call stack首先會放入全域執行環境(global EC),接著在全域執行環境執行程式碼遇到要呼叫函式的情況,就會建立該函式的執行環境(func1 EC)並且放入call stack,若是該函式內還有呼叫其他函式,同樣會建立其他函式的執行環境(func2 EC)並放入call stack。
等到最上層的函式執行完程式碼並且 return
以後,就會將最上層的函式執行環境(func2 EC)從stack中取出、移除,然後就最上層的函式執行環境去執行接下來的程式碼,同樣在函式 return
以後就會從call stack取出。
可以注意到,當call stack在執行當前最上層的執行環境程式碼時,其他執行環境的執行動作都會停擺,直到執行權回到其他執行環境。
而最底層的全域執行環境則會等到關閉瀏覽器或瀏覽氣分頁後才會從call stack取出。
Recap
最後簡單整理一下這篇文章的幾個重點:
準確地說,程式碼是在JavaScript引擎call stack的execution context中被執行;
Execution context是個會儲存所有跟程式碼執行相關資訊的執行環境,一般執行環境會包含變數(variable environment objects) ─ 像是var、let、const變數、函式定義、函式引數(arguments object),另外還會儲存scope chain和this key word;
- ⚠ 箭頭函式的執行環境不包含函式引數和this keyword。
JavaScript引擎的call stack會決定execution contexts的執行順序;
Call stack一次只會執行一個execution context(即stack最上層的execution context),且執行完後會被移出stack,好讓下層執行環境繼續運作;
全域執行環境(global execution context)只有在瀏覽器或分頁關閉時才會被移出call stack。
References
The Complete JavaScript Course 2023: From Zero to Expert!