介紹
大家好!
今天,正如標題所說,我將討論事件循環。
這不是面試官經常直接詢問的話題(我只記得有兩次他們讓我解釋事件循環)。但是,在大多數採訪中,他們會提出與之相關的問題。例如:
- “如果我這樣做…應該有什麼行為?”
- “如果我的程式碼如下所示,輸出會是什麼?”
- “為什麼這段程式碼會產生這樣的輸出?”
如果您了解事件循環的工作原理,那麼所有這些問題都會更容易回答。
老實說:這個話題不是我最喜歡的。我更喜歡詢問有關程式碼行為的問題,而不是解釋事件循環如何連續工作 10 分鐘。 ?
讓我們開始吧! ?
## 問題
1.什麼是事件循環?
2. 範例
什麼是事件循環?
簡短回答:
事件循環負責處理 JavaScript 執行階段中的非同步任務。
說實話,我認為這個答案不足以滿足面試官詢問事件循環的好奇心。因此,在這篇文章中,我想更深入地探討這個主題。
不僅僅是了解概念,了解如何它的工作原理也很重要。這就是為什麼我在最後添加了一些示例。
理論
什麼是事件循環?
JavaScript 有一個基於事件循環的執行時間,負責處理任務。每種語言都有獨特的運行時,需要注意的重要一點是 JavaScript 是單執行緒。
單線程是什麼意思?
單執行緒意味著JavaScript 一次只能處理一項任務。這就是為什麼事件循環在 JavaScript 中如此重要;儘管存在單執行緒限制,它仍然有助於有效地管理任務。
運行時的組成部分
為了更好地理解事件循環,我們先來看看它的主要組成部分:
呼叫堆疊
呼叫堆疊是一種資料結構,用來追蹤我們所呼叫的函數。你可以把它想像成一堆盤子:當一個函數被呼叫時,它被加到堆疊中,當它完成時,它被從堆疊中刪除。
呼叫堆疊遵循LIFO(後進先出) 原則,這意味著JavaScript 按照函數的堆疊順序執行函數— 從最上面的項目到底部,一個位於一次(記住,JavaScript 是單線程的)。
佇列
在 JavaScript 的執行時間中,我們有佇列,它保存要處理的任務清單。這些佇列中的任務會等待,直到呼叫堆疊為空。
任務佇列(或回調佇列):此佇列儲存諸如 setTimeout() 和 setInterval() 呼叫之類的任務。這裡的任務是在呼叫堆疊為空並且微任務佇列中的所有任務都處理完之後進行處理的。在 MDN 上查看儲存在此佇列中的任務的更多範例。
微任務佇列: 此佇列的優先權高於任務佇列。它包括微任務(例如 Promise 回調)和非同步函數(例如 process.nextTick() 和非同步函數)。
任務佇列以FIFO(先進先出)為基礎工作,這表示任務按照新增的順序進行處理,但僅在微任務之後進行佇列已空。
事件循環
事件循環是一種管理非同步程式碼執行的機制。它觀察呼叫堆疊以及呼叫堆疊和佇列(任務佇列和微任務佇列)之間的協調,以保持程式碼順利運行。
它是如何運作的?
讓我們一步步過一遍事件循環過程。請參閱下圖以獲得直觀表示。
在此範例中:
- 呼叫堆疊只有一個函數。
- 微任務佇列有兩個訊息。
- 任務佇列有訊息。
第 1 步:處理呼叫堆疊
- 事件循環從查看呼叫堆疊開始。
- 它在堆疊中找到一個函數並開始執行它。
- 此函數完成後,就會從呼叫堆疊中刪除。
步驟2:處理微任務隊列
- 呼叫堆疊為空後,事件循環會檢查微任務佇列。
- 它從微任務佇列取得第一個訊息並將其推送到呼叫堆疊來執行。
- 函數運行,一旦完成,就會從呼叫堆疊中刪除。
- 事件循環然後移動到微任務佇列中的下一則訊息並重複此過程。
- 這會持續到微任務佇列中不再有消息為止。
第三步:處理任務隊列
- 一旦呼叫堆疊和微任務佇列都為空,事件循環就會轉向任務佇列。
- 它選擇任務佇列中的第一個訊息並將其新增至呼叫堆疊。
- 函數運行,完成後,它會從呼叫堆疊中刪除。
- 事件循環將對任務佇列中的每個任務繼續此過程,確保所有任務都被一一處理。
依照這個順序-呼叫堆疊,然後微任務佇列,最後任務佇列-事件循環幫助JavaScript有效處理非同步程式碼,即使在它的單線程環境。
範例
現在我們了解了事件循環的工作原理以及任務的優先順序如何確定,讓我們來看一些範例。
實施例1
const a = new Promise(function showA(resolve){ console.log('A'); resolve('B'); }); setTimeout(function showC() { console.log('C'); }, 0); a.then(function showB(b) { console.log(b); }); const d = function showD() { console.log('D'); }; d();
在繼續之前,試著考慮一下輸出的順序。
✨你期望它是什麼? ✨
讓我們分解程式碼的每個部分來理解為什麼我們會得到這個輸出。
1。創造承諾
const a = new Promise(function showA(resolve) { console.log('A'); resolve('B'); });
- 在這裡,我們建立一個帶有回調函數的新 Promise。
- 在此函數內,console.log('A') 會立即執行,因此 "A" 會列印到控制台。
- 記錄「A」後,promise 被解析為值「B」。
- JavaScript 識別出有一個.then 回調(即showB),一旦主調用堆疊清除,該回調應該運行,因此它將showB 添加到微任務隊列(因為Promise 解析會去那裡) 。
2。 setTimeout 呼叫
setTimeout(function showC() { console.log('C'); }, 0);
- setTimeout 函數安排 showC 在 0 毫秒後運行。
- JavaScript 將 showC 放入任務佇列中,因為它是一個基於計時器的函數。
3。 a.then 回呼
const a = new Promise(function showA(resolve){ console.log('A'); resolve('B'); }); setTimeout(function showC() { console.log('C'); }, 0); a.then(function showB(b) { console.log(b); }); const d = function showD() { console.log('D'); }; d();
- 這行為我們在上一個步驟中已經解決的 Promise 註冊了一個 .then 處理程序 (resolve('B'))。
- 由於 Promise 已解決,showB(.then 回調)被加入到 微任務佇列。
4。定義 d
const a = new Promise(function showA(resolve) { console.log('A'); resolve('B'); });
- 這一行只是定義了函數 showD 但尚未執行它,所以這裡什麼也沒有發生。
5。呼叫 d()
setTimeout(function showC() { console.log('C'); }, 0);
- 現在,我們呼叫 d(),它被加到 呼叫堆疊 並執行。 這會產生 console.log('D'),因此 "D" 會列印到控制台。
最終輸出順序:
a.then(function showB(b) { console.log(b); });
GIF供參考
互動範例
實施例2
const d = function showD() { console.log('D'); };
再花點時間考慮輸出的順序。
✨你期望它是什麼? ✨
讓我們來解釋一下......
1。記錄「開始!」
d();
- 這行程式碼被加到呼叫堆疊並立即執行。
- 結果,「開始!」 被印到控制台。
- 設定超時調用
A D B C
- setTimeout 函數安排 showTimeout 在 0 毫秒後運行。
- JavaScript 將 showTimeout 放置在 任務佇列 中,因為它是一個基於計時器的函數。
3。承諾決議
console.log("Start!"); setTimeout(function showTimeout() { console.log("Timeout!"); }, 0); Promise.resolve("Promise!") .then(function showPromise(res) { console.log(res); }); console.log("End!");
- 承諾立即解決,值為「Promise!」。
- JavaScript 將 showPromise(.then 回呼)放入 微任務佇列,因為 Promise 在解析後會進入微任務佇列。
4。記錄「結束!」
console.log("Start!");
- 這行程式碼被加到呼叫堆疊並立即執行。
- 結果,「結束!」 被印到控制台。
最終輸出順序:
setTimeout(function showTimeout() { console.log("Timeout!"); }, 0);
GIF供參考
互動範例
結尾
本章並不太長,但我希望這些範例可以幫助您理解事件循環的工作原理。
我強烈建議嘗試互動頁面來分析其他範例。在該頁面上進行操作可以更輕鬆地理解正在運行的事件循環。
非常感謝大家對我之前貼文的喜愛!
下週見! ?
再見
以上是技術面試問題 - 部分事件循環的詳細內容。更多資訊請關注PHP中文網其他相關文章!

Python和JavaScript在社區、庫和資源方面的對比各有優劣。 1)Python社區友好,適合初學者,但前端開發資源不如JavaScript豐富。 2)Python在數據科學和機器學習庫方面強大,JavaScript則在前端開發庫和框架上更勝一籌。 3)兩者的學習資源都豐富,但Python適合從官方文檔開始,JavaScript則以MDNWebDocs為佳。選擇應基於項目需求和個人興趣。

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

JavaScript在現實世界中的應用包括服務器端編程、移動應用開發和物聯網控制:1.通過Node.js實現服務器端編程,適用於高並發請求處理。 2.通過ReactNative進行移動應用開發,支持跨平台部署。 3.通過Johnny-Five庫用於物聯網設備控制,適用於硬件交互。

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

本文展示了與許可證確保的後端的前端集成,並使用Next.js構建功能性Edtech SaaS應用程序。 前端獲取用戶權限以控制UI的可見性並確保API要求遵守角色庫

JavaScript是現代Web開發的核心語言,因其多樣性和靈活性而廣泛應用。 1)前端開發:通過DOM操作和現代框架(如React、Vue.js、Angular)構建動態網頁和單頁面應用。 2)服務器端開發:Node.js利用非阻塞I/O模型處理高並發和實時應用。 3)移動和桌面應用開發:通過ReactNative和Electron實現跨平台開發,提高開發效率。

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

ZendStudio 13.5.1 Mac
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 英文版
推薦:為Win版本,支援程式碼提示!

SublimeText3 Linux新版
SublimeText3 Linux最新版