### Function invocation & Execution stack: - Function invocation - 指調用(呼叫)函數的過程。 - Execution stack - 是**用來追蹤在程式碼執行過程中函數呼叫的一個資料結構**。它是一個**堆疊**(stack)結構,**遵循後進先出**(Last In, First Out,LIFO)的原則。 ### 函數的執行順序: - 這是一個簡單的範例,可以讓我們了解基本的執行順序與結果: ```js // call function & call stack: function b() { console.log("function b called!"); } function a() { console.log("function a called!"); b(); } a(); // outputs: function a called! function b called! ``` - 在 JavaScript 執行代碼時,誰會先被執行? - **Global Object**。 - 透過編譯器,執行代碼時,同時創造了: ```js Global Object & this 變數 // 若是在 Browser 瀏覽則是創建: window 物件。 ``` - 並將這些函數 setup 到**記憶體**中。 - 所以,你可以看見函數 a & b 都被設置在記憶體中了,直到被執行以前 他們會逐行去執行,直到它遇見你執行了函數 `a();` ```js // .. 前面代碼略過 a(); ``` ### 回到代碼本身,理解 Call Stack: ```js // 3. function b() { console.log("function b called!"); } // 2. function a() { console.log("function a called!"); b(); } a(); // 1. ``` 1. 一開始,我們已經提到: 在初期執行時,我們會創建一個叫做 Global Object 的全域物件 這時候函數與變數都會存儲在記憶體內,直到你去執行該函數。 2. 呼叫函數 a,此時,函數 a 會產生一個新的環境,而這個部分會被放進執行堆疊 - **Execution stack**。 3. 你可發現到,這個函數 a 裡頭也有呼叫函數 b,故函數 a 環境執行到 ```js // call b() b(); // 這時候會產生一個函數 b 的執行環境堆疊 ``` - 所以呢,每個函數都代表了一個環境,當執行到該函數時,就會被放進執行堆疊 - Stack,最上方則是當前被執行的 Stack。 - ![截圖 2023-12-06 下午3.27.48](https://hackmd.io/_uploads/H1QKGipSa.png) ### 執行堆疊如何進出,下一道案例: ```js // call function & call stack: function a() { b(); var c; console.log("c"); // 3. console.log(c); // 4. } function b() { var d; console.log("d"); // 1. console.log(d); // 2. } a(); var d; ``` - 細說這段流程: 1. 代碼先進入全域執行環境,此時函數 a,b、變數 d 都被存在記憶體。 2. 先執行了函數 a,創建了函數 a 執行堆疊環境 - 此時進入 `Execution Context a();` - 這時會先跑函數 b,這時候則進入: `Execution Context b(); ` - 口訣:**後進,先出。** ```jsx // Execution Context b(); -> 我們將函數 b 內容給執行完成,離開堆疊。(1) // Execution Context a(); -> 回頭執行函數 a 尚未完成的部分,直到完成,離開堆疊。(2) // Global Execution Context -> 最後,回到全局環境,將剩餘的 var d 給完成宣告。(3) ```