搜尋
首頁web前端前端問答完全掌握JavaScript執行機制

這篇文章為大家帶來了關於JavaScript執行機制的相關問題,其中包括JavaScript單執行緒和JavaScript同步非同步的相關知識,希望對大家有幫助。

完全掌握JavaScript執行機制

一、為什麼JavaScript是單執行緒

如果想了解JavaScript為什麼是單執行緒的,我們就要從JavaScript是用來做什麼工作的來入手。

JavaScript作為瀏覽器的腳本語言,產出的目的就是為了瀏覽器與使用者進行交互,操作DOM元素,從而提升使用者的交互及體驗感。 JavaScript要操作瀏覽器的DOM元素,因此導致JavaScript無法成為多執行緒語言,我們假設一個場景,如果JavaScript是多執行緒語言,兩個執行緒同時操作一個DOM元素,一個執行緒需要編輯更新DOM元素,而另一個則是刪除DOM元素節點,這是瀏覽器該以哪一個為準呢?

同一時間只能做同一件事情,因為操作DOM元素的原因,導致單執行緒是JavaScript這門語言的核心,也是這門語言特點。

HTML5提出Web Worker標準,允許JavaScript腳本建立多個線程,但是子執行緒完全受主執行緒控制,且不得操作DOM。即使這樣的改動也並沒有改變js單執行緒的本質。

二、JavaScript中的同步與非同步

javaScript的單執行緒機制,就導致同一時間只能做一件事情。就像一堆人在ATM提款機提款,即使後面再多的人在著急,也只能一個一個的排隊,等待前一個人取完款,才能輪到後一人。

可是這樣會導致如果說前一個任務消耗時間過長,後一個任務就會等待非常久,比如,我們需要加載一個數據量非常大的Ajax請求,我們不得不等待請求相應結果,再繼續往下行執後續任務。

那我們該如何處理這種情況呢?既然我們無法改變JavaScript的單執行緒機制,我們是否可以將一些耗時久的任務進行暫時掛起,等到主任務執行完成之後,再將這些掛載的任務執行。 JavaScript的作者也想到了這樣的方式,JavaScript擁有了同步任務與非同步任務。

同步任務就是,任務在主執行緒上進行排隊,下一個任務必須等待上一個任務執行完成,才可以執行。而非同步任務是指,任務不進入主線程,而進入任務隊列(task queue)進行等待,進入任務隊列的任務只有"任務隊列"通知主線程,某個非同步任務可以執行了,該任務才會進入主線程執行。

三、Event Loop事件循環機制

JavaScript的所有同步任務都在主執行緒上執行,形成執行端。

任務佇列是先進先出的原則,先進佇列的事件先執行,後進佇列的事件後執行。

Event Loop

  • #執行執行堆疊中的同步任務。

  • 當遇到一個非同步任務後不會一直等待其回傳結果,會先將非同步任務暫時掛起,繼續執行其他的同步任務。

  • 當非同步任務有結果之後,JavaScript會任務將會加入到任務佇列中。被加入到任務佇列中的任務不會立刻進行回調執行而是等待主執行緒(執行堆疊)空閒時才加入執行棧中進行回調執行

  • 等待執行堆疊中的任務執行完畢。

  • 將任務佇列中的任務加入執行堆疊後執行。

如此反复,這樣就形成了一個無限的循環(event loop)。 (下圖來自網路)

完全掌握JavaScript執行機制

學習了Event Loop 我們一起來看看下面這題:

setTimeout(function(){
     console.log('setTimeout start')
 });
 new Promise(function(resolve){
     console.log('promise start');
     resolve()
 }).then(function(){
     console.log('promise then')
 });
 console.log('script end');

試試看按照,上文我們剛學到的JavaScript執行機制去分析

 1. 先執行同步任務,執行到setTimeout,但是setTimeout是非同步任務的暫時掛起,等待計時逾時,加入到任務佇列中。

 2. 繼續往下,在執行到new Promise,new Promise裡面的是同步任務,印出 "promise start"。

 3. 在執行到resolve將.then加入任務佇列中。

 4. 在執行 console.log('script end');列印"script end"。

 5. 這時主任務都已經執行完成,在將非同步任務加入主任務中直接執行,列印"setTimeout start",再將.then加入主任務中,列印"promise then" 。

所以結果應該是:promise start -> script end -> setTimeout start -> promise then 嗎?

親自在瀏覽器執行後,結果居然不是這樣,而是promise start -> script end -> promise then -> setTimeout start

巨集任務與微任務

那為什麼上文的結果為什麼跟我們預想的不一致,為什麼 setTimeout start 會在 promise 之後列印。

其實是因為非同步的執行也是有先後順序的。其實用異步跟同步的方式去劃分任務隊列的執行順序是不準確的。應該劃分為 微任務 與 宏任務。

  • 巨集任務(macro-task):script 程式碼、setTimeout、setInterval

  • 微任務(micro-task):Promise、process. nextTick

所以說setTimeout是非同步任務中的巨集任務,而Promise是非同步任務中的微任務。不管是 微任務 還是 巨集任務,都會進入對應的 Event Queue, 接下來我們在看一個流程圖。

完全掌握JavaScript執行機制

我們來稍微理解一下:

  • # 1.執行巨集任務(script程式碼)

  •  2. 當執行巨集任務的時遇到了微任務,就會將微任務加入Event Queue

  •  3. 在目前巨集任務執行完成後,會檢視微任務的Event Queue ,並將裡面全部的微任務依序執行完

  •  4. 在執行玩所有的為微任務之後,繼續進行第一步,以此循環

這便也是javaScript 的運作機制,結合這個我們再重新的分析一下上面的範例。

  •  1. 首先執宏任務(script代碼 ),遇到setTimeout將其加入進宏任務的Event Queue。

  •  2. 繼續往下,在執行到new Promise,列印 "promise start"。

  •  3. 在執行到resolve,.then是微任務,加入進微任務的Event Queue。

  •  4. 在執行 console.log('script end');列印 "script end"。

  •  5. 到這裡本輪的巨集任務就已經全部執行結束了,這時查找微任務的Eevent Queue 是否存在可執行的微任務, 發現有剛才在第三步驟加進去額度.then,執行並列印"promise then"

  • # 6. 這時第一輪的event loop 就已經徹底結束了,下一輪event loop 先執行一個巨集任務,發現巨集任務的Event Queue中有新增的setTimeout,執行並列印"setTimeout start"

永遠記住JavaScript是單線程,以前是、現在是、將來也會是。所有的多線說法都是扯淡。

即使是Event Queue,也只不是實作非同步的方式,也是js的執行機制。

以後能用JavaScript實現的。都會用JavaScript來實作。

相關推薦:javascript學習教學

#

以上是完全掌握JavaScript執行機制的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:掘金。如有侵權,請聯絡admin@php.cn刪除
HTML和React的集成:實用指南HTML和React的集成:實用指南Apr 21, 2025 am 12:16 AM

HTML與React可以通過JSX無縫整合,構建高效的用戶界面。 1)使用JSX嵌入HTML元素,2)利用虛擬DOM優化渲染性能,3)通過組件化管理和渲染HTML結構。這種整合方式不僅直觀,還能提升應用性能。

React和HTML:渲染數據和處理事件React和HTML:渲染數據和處理事件Apr 20, 2025 am 12:21 AM

React通過state和props高效渲染數據,並通過合成事件系統處理用戶事件。 1)使用useState管理狀態,如計數器示例。 2)事件處理通過在JSX中添加函數實現,如按鈕點擊。 3)渲染列表需使用key屬性,如TodoList組件。 4)表單處理需使用useState和e.preventDefault(),如Form組件。

後端連接:反應如何與服務器互動後端連接:反應如何與服務器互動Apr 20, 2025 am 12:19 AM

React通過HTTP請求與服務器交互,實現數據的獲取、發送、更新和刪除。 1)用戶操作觸發事件,2)發起HTTP請求,3)處理服務器響應,4)更新組件狀態並重新渲染。

反應:專注於用戶界面(前端)反應:專注於用戶界面(前端)Apr 20, 2025 am 12:18 AM

React是一種用於構建用戶界面的JavaScript庫,通過組件化開發和虛擬DOM提高效率。 1.組件與JSX:使用JSX語法定義組件,增強代碼直觀性和質量。 2.虛擬DOM與渲染:通過虛擬DOM和diff算法優化渲染性能。 3.狀態管理與Hooks:Hooks如useState和useEffect簡化狀態管理和副作用處理。 4.使用示例:從基本表單到高級的全局狀態管理,使用ContextAPI。 5.常見錯誤與調試:避免狀態管理不當和組件更新問題,使用ReactDevTools調試。 6.性能優化與最佳

React的角色:前端還是後端?澄清區別React的角色:前端還是後端?澄清區別Apr 20, 2025 am 12:15 AM

reactisafrontendlibrary,focusedonBuildingUserInterfaces.itmanagesuistateandupdatesefficefited avelyuseVirusity diftualdom,and internactSwithBackendServIcesViaApisforDatahandling,butdoesnotprocessorcorsorsorstoredordordordoredairself。

在HTML中進行反應:構建交互式用戶界面在HTML中進行反應:構建交互式用戶界面Apr 20, 2025 am 12:05 AM

React可以嵌入到HTML中來增強或完全重寫傳統的HTML頁面。 1)使用React的基本步驟包括在HTML中添加一個根div,並通過ReactDOM.render()渲染React組件。 2)更高級的應用包括使用useState管理狀態和實現複雜的UI交互,如計數器和待辦事項列表。 3)優化和最佳實踐包括代碼分割、惰性加載和使用React.memo和useMemo來提高性能。通過這些方法,開發者可以利用React的強大功能來構建動態和響應迅速的用戶界面。

反應:現代前端發展基礎反應:現代前端發展基礎Apr 19, 2025 am 12:23 AM

React是構建現代前端應用的JavaScript庫。 1.它採用組件化和虛擬DOM優化性能。 2.組件使用JSX定義,狀態和屬性管理數據。 3.Hooks簡化生命週期管理。 4.使用ContextAPI管理全局狀態。 5.常見錯誤需調試狀態更新和生命週期。 6.優化技巧包括Memoization、代碼拆分和虛擬滾動。

React的未來:Web開發的趨勢和創新React的未來:Web開發的趨勢和創新Apr 19, 2025 am 12:22 AM

React的未來將專注於組件化開發的極致、性能優化和與其他技術棧的深度集成。 1)React將進一步簡化組件的創建和管理,推動組件化開發的極致。 2)性能優化將成為重點,特別是在大型應用中的表現。 3)React將與GraphQL和TypeScript等技術深度集成,提升開發體驗。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

SublimeText3 英文版

SublimeText3 英文版

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

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境