在 JavaScript 裡面,一個很重要的概念就是 Event Loop,是 JavaScript 底層在執行程式碼時的運作方式。請你說明以下程式碼會輸出什麼,以及盡可能詳細地解釋原因。
console.log(1)
setTimeout(() => {
console.log(2)
}, 0)
console.log(3)
setTimeout(() => {
console.log(4)
}, 0)
console.log(5)
輸出:
1
3
5
2
4
JavaScript 是單執行緒的語言,也就是一次只能做一件事。所以遇到非同步程式碼時,要先把他交給 Web API 使用瀏覽器的其他執行緒處理,才不會 block 原本的程式碼執行。等到 Web API 把非同步的操作處理完,再把當初設定好的 callback 帶上資料,放到 task queue,等到 JavaScript 有空時(call stack 為空)再執行。
- 把
main()
放到 call stack 上,執行裡面的程式碼。 - 把
console.log(1)
放到 call stack 上,執行程式碼印出1
,結束後把它從 stack 上清除。 - 把
setTimeout(() => {console.log(2)}, 0)
放到 call stack 上。因為是非同步的函式,呼叫 Web API 執行並從 stack 上清除。因為setTimeout
設定零秒,Web API 馬上把() => {console.log(2)}
丟到 task queue 裡面等待執行。 - 把
console.log(3)
放到 call stack 上,執行程式碼印出3
,再從 stack 上清除。 - 如第二步,把
setTimeout(() => {console.log(4)}, 0)
放到 call stack 上、() => {console.log(4)}
丟給 Web API、零秒後() => {console.log(4)}
放入 task queue。 - 把
console.log(5)
放到 call stack 上,執行印出5
,從 call stack 上清除。 - 把
main()
從 call stack 上清除。 - call stack 為空,把 task queue 第一個 function,也就是
() => {console.log(2)}
放到 call stack 上執行,印出2
,移出 call stack。 - call stack 為空,把 task queue 第一個 function
() => {console.log(4)}
放到 call stack 上執行,印出4
,移出 call stack。
推 What the heck is the event loop anyway? | Philip Roberts | JSConf EU 的 視覺化網站。