iT邦幫忙

2022 iThome 鐵人賽

DAY 8
2
Modern Web

擊敗前端面試大作戰!系列 第 8

[擊敗前端面試大作戰] The Execution Context, Call-stack and Event Loop

  • 分享至 

  • xImage
  •  

今天呢要來講一個我覺得很有趣的題目---Event loop,這題在面試中被問到的機會非常的高,我自己就有在面試中被問到超過兩次!所以如果在面試中可以把這題回答得很好,我覺得是會讓面試官眼睛一亮的!那我們就進入主題吧~

什麼是 Event Loop 事件循環

回答:Event Loop 是一個 JS 的機制,讓我們可以處理非同步的動作。

Event Loop 解決了什麼問題?

回答:JS 本身是 單線程序(single-threaded),代表一次只能有一件事能被執行,所以當出現一個很大的計算的時候,就會導致後面的計算沒辦法被執行。而透過 Event Loop 我們可以解決這個問題。

面試回答思路:回答 event loop 解決的問題,然後帶到 The Execution Context 跟 Call-stack。

沒聽過這兩個名詞The Execution ContextThe Call-stack的話沒關係,下面我們就來討論這兩個東西吧!

The Execution Context

你有沒有想過一個問題,當你在瀏覽器上面跑 Js 得時候,背地裡發生了什麼事情?瀏覽器是怎麼執行我們傳送給他的 Js 程式碼的?或是像上面這段程式碼在執行時,到底瀏覽器是怎麼去跑他的?

要回答這些問題,我們必須先講到The Execution Context

當一段程式碼被執行時,會先產生 全局的 Execution Context。然後 瀏覽器引擎 進入 creation phase ,有四件事情會發生:

  1. 建立 全局 物件,它在 瀏覽器 中被稱作window,在 Node 中被稱作global
  2. 建立 this 並且指向 全局 物件
  3. 建立一個 memory heap 來儲存 變數 和 函式的 references
  4. 把 函式宣告式 (ex, function s()...)儲存在 memory heap 中, 然後把 memory heap 裡面的 變數 賦予undefined。這一點蠻重要的,因為也就是這樣所以我們才能在宣告 function 之前就使用 function
const a = 10;

function text() {
  return "text";
}

所以以上面的程式碼為例,這時候我們的 全局的 Execution Context 會有以下幾個東西,

  1. 全局 物件,裡面的值是 window
  2. this,也指向 window
  3. a,值是 undefined
  4. function text

 

不知道大家還記不記得 let, const 和 var 那篇文章,裡面有個例子長這樣,

printName(); //John

function printName() {
  console.log("John");
}

然後當時我說function 會被 hoisted,但是可以被使用。,現在了解Execution Context的機制後,我們終於知道為什麼 function 可以被提前使用了!因為全局The Execution Context被建立時就會先把 function 儲存在 memory heap 中!!

回到剛剛的情況,在creation phase完成後,瀏覽器 會進入下一個階段-----execution phase

在這個階段,程式碼會被一條條的執行,

  1. 變數 會被賦予值,
  2. function 會被執行,並且在每個 function 被執行時,瀏覽器引琴 都會 建立 一個 Function Execution Context (類似上面的 全局 Execution Context),但是 全局 物件會被指到 arguments物件,裡面會儲存所有傳進 function 的值。

這個階段後, 全局的 Execution Context會長這樣:

  1. 全局 物件,裡面是 window
  2. this,也指向 window
  3. a,值為 10
  4. function text

以上就是瀏覽器在跑 JS 檔案時所發生的事情!

 

這時候有個問題來了,當我們出現多個嵌套的(nested)函式時,我們已經知道會觸發多個Function Execution Context,那瀏覽器引擎又要怎麼去執行這些函式呢?這就要談到The Event Loopcallback queue了!但在那之前,我們還先需要知道兩個東西The Call-stackThe callback queue

 

The Call-stack

: The call-stack 是一種資料結構(stack)用來追蹤和管理function execution

實際情況:The call-stack 依照 Last In First Out 的規矩,當 瀏覽器引擎 執行 到 函式 時,會把該 函式 push 到 call-stack 裡,並且在執行該 函式 時,會把該 函式 從call-stack 中 pop 掉,

https://ithelp.ithome.com.tw/upload/images/20220922/20148825Zr1xlOJA5K.jpg
 

The callback queue

: The callback queue是一種資料結構 queue 用來追蹤跟管理需要被晚點執行的事件,包含 setTimeout, setInterval 等等。First-in, First-out

這裡只有簡略講解 stack 和 queue,實際的實踐方式有興趣的讀者可以上網自行研究摟

The Event Loop and The callback queue

解決的問題:讓 JS 可以執行非同步的動作(ex, network request)

 

https://ithelp.ithome.com.tw/upload/images/20220922/20148825DGUwGA34NJ.jpg)

講了這麼多,現在終於講到 event loop 的精彩階段了!The event loop會去追蹤 call-stack中需要執行 非同步 的 函式,當執行到該 函式 時把他丟入callback queue中,

  1. call-stack其他 function 都執行完,變回空的時候。
  2. 處理 callback queue中的 function 丟回到call-stack上來執行。

callback queue的執行順序為: Microtask > Macrotask

常見的 microTask: Promise
常見的 macroTask: setTimeout, setInterval... (與瀏覽器或電腦底層的運作較有關係)

所以來總結一下。今天先談到了execution context跟瀏覽器在執行中所有的兩個階段,包括creation phaseexecution phase,然後我們又講到要解決非同步問題我們需要call-stackcallback-queue這兩個東西,最後這些所組成的用來處理非同步的機制,就叫做event loop!那下面有一個小面試題目就留給讀者來嘗試看看摟!我們明天見!

setTimeout(() => alert("timeout"));

Promise.resolve().then(() => alert("promise"));

alert("global ex. context");

 

Resources

https://dev.to/thebabscraig/the-javascript-execution-context-call-stack-event-loop-1if1
https://pjchender.dev/javascript/note-event-loop-microtask/

https://www.educative.io/answers/what-is-an-event-loop-in-javascript

keyword: Global Execution Context, creation phase, execution phase


上一篇
[擊敗前端面試大作戰] prototype and prototype chain
下一篇
[擊敗前端面試大作戰] Polyfills and Transpiler
系列文
擊敗前端面試大作戰!30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言