---
# System prepended metadata

title: 克服 JS 奇怪的部分 04. 函數呼叫(Call Function) & 執行堆疊(Stack)
tags: ["JavaScript\_", JavaScript 基礎]

---

### 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)
```