iT邦幫忙

2021 iThome 鐵人賽

DAY 7
0
Modern Web

舌尖上的JS系列 第 7

D7 - 你不知道Combo: 第二主菜 Execution Context

  • 分享至 

  • xImage
  •  

前言

JavaScript 可以隨時隨地呼叫函式,像 function A 呼叫了 function B,執行完 function B 又回到 function A,不禁好奇想問,引擎是怎麼知道該執行哪個 function、順序誰先誰後?

吃完這第二道主菜 執行背景空間 Execution Context(EC) 你就懂了,上菜!

執行背景空間 Execution Context

在 JavaScript 執行程式時,其實都是在一個 Execution Context 執行背景空間內進行,函式是最基本的執行單位,每個 function 都有一個背景執行空間,函式背景空間分為兩種:

  1. 全域背景執行空間

全域的背景執行空間只會有一個,以下稱 全域 EC

  1. 函式執行背景空間

而每次呼叫 function 就會創立一個新的函式執行背景空間,以下稱 function EC

好的,那創立了這麼多個 EC,怎麼決定誰先執行?
JavaScript 是單執行緒的語言,一次只能做一件事,總不會每次都靠剪刀石頭布決定吧。

一個最簡單的方法就是,將每個 EC 像樂高般一個個堆疊排好,從最頂端開始拿,新加入的 EC 再繼續堆疊放上去,執行完畢就把它拿下來,他們堆疊的地方稱為 Execution Context Stack  或更常被稱呼為  呼叫堆疊 Call Stack


圖片取自CLEANPNG

呼叫堆疊 Call Stack

Call Stack 內會堆疊著一個個 EC,協助引擎追蹤所有待執行的函式,呼叫一個 function 就會有一個新的 EC 被創造,並放入 Call Stack 中,待結束再從堆疊中彈出。

通常會說 push 放入、pop 彈出(好嫩Q)

在一些文章中會看到一個專有名詞 LIFO(Last-in-first-out)後進先出,用來表示比較晚放入 Call Stack 的 EC,執行完畢後會先 pop 彈出

「嘿,菜鳥結束快閃。」

舉一個例子實際來看看

function getCookie(cookie){
    console.log(cookie);
}

function afternoonTea (biscuit){
  getCookie(biscuit)
}

afternoonTea ('Oreo');

上面的程式碼定義了兩個 function,第 1 個 function getCookie 會印出 cookie,第 2 個 function afternoonTea 會呼叫第 1 個 function getCookie

讓我們來呼叫function afternoonTea 看看 Call Stack 是怎麼堆疊的?

  1. 開始執行程式,這時全域 EC 被創造出來,並放入 Call Stack 內
  2. 呼叫 function afternoonTea,一個新的 EC 被創造然後放入 Call Stack 的頂端
  3. 開始執行 afternoonTea 內呼叫 function getCookie 的動作,又一個新的 EC 被創造出來放入 Call Stack 頂端,執行 getCookie 印出 'Oreo'
  4. 當執行完 getCookie,它的 EC 會從 Call Stack 中彈出,這時最頂端的 EC 是 afternoonTea,很好,引擎知道再來該執行誰
  5. afternoonTea 執行完畢也被彈出,這時 Call Stack 剩下一個全域 EC,當全域內的程式執行完畢後彈出,掰掰,沒有任何待執行的 EC 在 Call Stack 中,執行完畢!

以上就是 Call Stack 執行的結果,依照程式碼執行的過程不斷有 EC 被 push 進又 pop 出,直到 Call Stack 內不再有任何 EC,程式也就執行完畢。

和 Lexical Environment 的關係?

以上擷自 ECMA 9.4 Execution Context 的內容,提到了 字彙環境 Lexical Environment 是 EC 的一個 component,執行背景空間 EC 可以透過 字彙環境 Lexical environment 來解析識別項,就是查找所有的變數及 function 的動作。
哇!與前一道菜的觀念串起來了呢,所以有些文章講 Hoisting 時會從 EC 講起,因為 EC 都有自己相關聯的字彙環境存放變數、參數及 function 值的地方。

結語

本來還想繼續講執行背景空間 Execution Context 與 字彙環境 Lexical Environment 的圖例,但昨天接到食客反應篇幅太長吃到快吐,決定這部分留到 Closure 的時候再繼續吧!
~少量多餐有益健康~

Reference:

書籍:
你所不知道的JS  by Kyle Simpon
忍者 JavaScript 開發技巧探秘第二版  by John Resig, Bear Bibeault, Josip Maras

文章:
The JavaScript Call Stack
我知道你懂 hoisting,可是你了解到多深?
ECMA
JavaScript Execution Context


上一篇
D6 - 你不知道 Combo : 主菜 Scope 字彙環境
下一篇
D8 - 你不知道Combo : 甜點用一杯 Mojito 解釋 直譯器、編譯器
系列文
舌尖上的JS30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

0
Chiahsuan
iT邦新手 4 級 ‧ 2021-09-22 14:42:22

喜歡你畫的EC插圖(重點錯誤)
/images/emoticon/emoticon32.gif

0
南國安迪
iT邦新手 3 級 ‧ 2021-09-22 18:29:21

這次相信我有認真看了吧XD

我要留言

立即登入留言