摘要:事件表每次調(diào)用函數(shù)或執(zhí)行異步操作時,都會將其添加到事件表中,事件表負(fù)責(zé)記錄每個事件完成后執(zhí)行的回調(diào)函數(shù),并監(jiān)聽事件,事件完成后會把事件的回調(diào)函數(shù)發(fā)送到事件隊列。事件隊列事件隊列接收來自事件表的回調(diào)函數(shù),并根據(jù)順序執(zhí)行。
前言
先上一段代碼,可以根據(jù)自己之前對JS執(zhí)行機(jī)制的理解,進(jìn)行分析
console.log("script start"); setTimeout(function() { console.log("setTimeout"); }, 0); Promise.resolve().then(function() { console.log("promise1"); }).then(function() { console.log("promise2"); }); console.log("script end");
答案:
script start
script end
promise1
promise2
setTimeout
如果自己的答案和上面的答案有出入,請繼續(xù)閱讀
基本概念的闡述調(diào)用堆棧
JavaScript有一個多帶帶的調(diào)用堆棧,負(fù)責(zé)執(zhí)行JS代碼,當(dāng)即將執(zhí)行一個函數(shù)時,此函數(shù)就會被添加到調(diào)用堆棧中,當(dāng)此函數(shù)執(zhí)行完,則會出棧。
事件表
每次調(diào)用setTimeout函數(shù)或執(zhí)行異步操作時,都會將其添加到事件表中,事件表負(fù)責(zé)記錄每個事件完成后執(zhí)行的回調(diào)函數(shù),并監(jiān)聽事件,事件完成后會把事件的回調(diào)函數(shù)發(fā)送到事件隊列。
事件隊列
事件隊列接收來自事件表的回調(diào)函數(shù),并根據(jù)順序執(zhí)行。事件隊列中存儲兩種任務(wù): 微任務(wù)和宏任務(wù)
在當(dāng)前的微任務(wù)沒有執(zhí)行完成時,是不會執(zhí)行下一個宏任務(wù)的。
這里有兩種說法,一種說法把剛開始執(zhí)行的整體JS代碼認(rèn)為是一個宏任務(wù),先執(zhí)行整體JS代碼這一個宏任務(wù),執(zhí)行完成后,再執(zhí)行微任務(wù)列表中的所有微任務(wù),所以認(rèn)為先執(zhí)一個行宏任務(wù)再執(zhí)行所有微任務(wù)
另外一種說法沒有把剛開始的JS代碼當(dāng)做宏任務(wù),所以起始執(zhí)行的是微任務(wù),所有微任務(wù)執(zhí)行完再執(zhí)行宏任務(wù),認(rèn)為先執(zhí)行微任務(wù)再執(zhí)行宏任務(wù)
其實(shí)兩種說法的核心是一樣的,都是執(zhí)行一個宏任務(wù) 執(zhí)行所有微任務(wù)
事件循環(huán)
事件循環(huán)就是一個持續(xù)運(yùn)行的進(jìn)程,用于檢查調(diào)用堆棧是否為空。將我們上面所述連接起來,并循環(huán)執(zhí)行。
JS執(zhí)行機(jī)制console.log("script start"); setTimeout(function() { console.log("setTimeout"); }, 0); Promise.resolve().then(function() { console.log("promise1"); }).then(function() { console.log("promise2"); }); console.log("script end");
再次分析此段代碼
最初始狀態(tài):JS調(diào)用棧為空,任務(wù)隊列中宏任務(wù)隊列有script代碼塊就緒
第一步:檢查調(diào)用棧為空,將宏任務(wù)script入棧,開始向下執(zhí)行
第二步:當(dāng)遇到異步操作時,執(zhí)行異步,并將異步事件與其回調(diào)函數(shù)注冊到事件列表,同步代碼繼續(xù)執(zhí)行
第三步:當(dāng)事件表監(jiān)聽到異步事件已經(jīng)完成,將其事件的回調(diào)函數(shù)入隊(任務(wù)隊列)
第四步:檢查到調(diào)用棧為空,先將微任務(wù)依次入棧(調(diào)用堆棧)執(zhí)行,微任務(wù)列表為空時,將宏任務(wù)入棧(調(diào)用堆棧)執(zhí)行
更多關(guān)于JS執(zhí)行機(jī)制的理解請點(diǎn)擊下面鏈接,有動畫效果有助于理解 特別推薦
Tasks, microtasks, queues and schedules
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/109138.html
摘要:深入理解引擎的執(zhí)行機(jī)制靈魂三問為什么是單線程的為什么需要異步單線程又是如何實(shí)現(xiàn)異步的呢中的中的說說首先請牢記點(diǎn)是單線程語言的是的執(zhí)行機(jī)制。 深入理解JS引擎的執(zhí)行機(jī)制 1.靈魂三問 : JS為什么是單線程的? 為什么需要異步? 單線程又是如何實(shí)現(xiàn)異步的呢? 2.JS中的event loop(1) 3.JS中的event loop(2) 4.說說setTimeout 首先,請牢記2...
摘要:深入理解引擎的執(zhí)行機(jī)制最近在反省,很多知識都是只會用,不理解底層的知識。在閱讀之前,請先記住兩點(diǎn)是單線程語言的是的執(zhí)行機(jī)制。所以,是存在異步執(zhí)行的,比如單線程是怎么實(shí)現(xiàn)異步的場景描述通過事件循環(huán),所以說,理解了機(jī)制,也就理解了的執(zhí)行機(jī)制啦。 深入理解js引擎的執(zhí)行機(jī)制 最近在反省,很多知識都是只會用,不理解底層的知識。所以在開發(fā)過程中遇到一些奇怪的比較難解決的bug,在思考的時候就會收...
摘要:一直以來,對的執(zhí)行機(jī)制都是模棱兩可,知道今天看了文章這一次,徹底弄懂執(zhí)行機(jī)制和的規(guī)范和實(shí)現(xiàn),才對的執(zhí)行機(jī)制有了深入的理解,下面是我的學(xué)習(xí)總結(jié)。個要點(diǎn)是單線程語言是的執(zhí)行機(jī)制,為了實(shí)現(xiàn)主線程的不阻塞,就這么誕生了。 一直以來,對JS的執(zhí)行機(jī)制都是模棱兩可,知道今天看了文章—《這一次,徹底弄懂JavaScript執(zhí)行機(jī)制》和《Event Loop的規(guī)范和實(shí)現(xiàn)》,才對JS的執(zhí)行機(jī)制有了深入的...
摘要:心塞塞根據(jù)規(guī)范,事件循環(huán)是通過任務(wù)隊列的機(jī)制來進(jìn)行協(xié)調(diào)的。等便是任務(wù)源,而進(jìn)入任務(wù)隊列的是他們指定的具體執(zhí)行任務(wù)回調(diào)函數(shù)。然后當(dāng)前本輪的結(jié)束,主線程可以繼續(xù)取下一個執(zhí)行。 依然是:經(jīng)濟(jì)基礎(chǔ)決定上層建筑。 說明 首先,旨在搞清常用的同步異步執(zhí)行機(jī)制 其次,暫時不討論node.js的Event Loop執(zhí)行機(jī)制,以下關(guān)于瀏覽器的Event Loop執(zhí)行機(jī)制 最后,借鑒了很多前輩的研究文...
摘要:異步任務(wù)必須指定回調(diào)函數(shù),當(dāng)異步任務(wù)從任務(wù)隊列回到執(zhí)行棧,回調(diào)函數(shù)就會執(zhí)行。事件循環(huán)主線程從任務(wù)隊列中讀取事件,這個過程是循環(huán)不斷的,所以整個的這種運(yùn)行機(jī)制又稱為。事件循環(huán)事件循環(huán)是指主線程重復(fù)從消息隊列中取消息執(zhí)行的過程。 參考鏈接:這一次,徹底弄懂 JavaScript 執(zhí)行機(jī)制https://zhuanlan.zhihu.com/p/...從瀏覽器多進(jìn)程到JS單線程,JS運(yùn)行機(jī)制...
閱讀 2049·2023-04-25 15:11
閱讀 3496·2021-09-23 11:57
閱讀 1384·2021-07-26 23:38
閱讀 1326·2019-08-30 15:54
閱讀 645·2019-08-30 15:53
閱讀 3254·2019-08-26 13:36
閱讀 997·2019-08-26 12:01
閱讀 2871·2019-08-23 16:21