摘要:一直以來,對的執行機制都是模棱兩可,知道今天看了文章這一次,徹底弄懂執行機制和的規范和實現,才對的執行機制有了深入的理解,下面是我的學習總結。個要點是單線程語言是的執行機制,為了實現主線程的不阻塞,就這么誕生了。
一直以來,對JS的執行機制都是模棱兩可,知道今天看了文章—《這一次,徹底弄懂JavaScript執行機制》和《Event Loop的規范和實現》,才對JS的執行機制有了深入的理解,下面是我的學習總結。
2個要點JS是單線程語言
Event Loop是JS的執行機制,為了實現主線程的不阻塞,Event Loop就這么誕生了。
2個概念(結合Browser環境和Node環境)task queue(宏任務隊列):setTimeout、setInterval、setImmediate、I/O、UI交互事件
microtask queue(微任務隊列):Promise、process.nextTick、MutaionObserver
看下圖:
queue可以看成一種數據結構,用以存儲需要執行的函數
setTimeout等API注冊的函數,會進入task隊列
Promise等API注冊的函數會進入microtask隊列
Event Loop執行一次,從task隊列中拉出一個task執行
Event Loop繼續檢查microtask隊列是否為空,依次執行直至清空隊列
情景再現JS的執行邏輯,就好比只有一個窗口的銀行,客戶需要一個一個排隊辦理業務,假如現在排隊的有兩個人,第一個人是辦理銀行卡的,第二個人是取錢的,下面來個情景對話(這就類似上圖的event loop):
客服:請問您辦理什么業務?
客戶1:辦理銀行卡。
客服:請先填寫一份申請表。下一位!(此時客戶1進入callback queue)
客服:請問您辦理什么業務?
客戶2:取錢
…………
(此時客戶1已經完成申請表填寫,但客戶2還未結束,那么客戶1還需等待,直到窗口前的這個客戶辦理結束)
客戶1:我填好了,給您……
## 實例練習1
console.log(1) setTimeout(() => { console.log(2) new Promise(resolve => { console.log(4) resolve() }).then(() => { console.log(5) }) }) new Promise(resolve => { console.log(7) resolve() }).then(() => { console.log(8) }) setTimeout(() => { console.log(9) new Promise(resolve => { console.log(11) resolve() }).then(() => { console.log(12) }) })
分解動作:
主進程運行的代碼首先輸出1、7;
再執行一次microtask輸出8;
執行了一次task輸出2,4;
再執行一次microtask輸出5;
再執行另一個task輸出9、11;
再執行一次microtask輸出12
最終結果:
1、7、8、2、4、5、9、11、12
注意的:在Node環境下process.nextTick注冊的函數優先級高于Promise,大家可以在Node環境下嘗試下面的例子:
new Promise(resolve => { console.log(1) resolve() }).then(() => { console.log(2) }) new Promise(resolve => { console.log(3) resolve() }).then(() => { console.log(4) }) process.nextTick(() => { console.log(5) }) console.log(6)
執行結果:1、3、6、5、2、4
實例練習2setTimeout(() => { console.log(2) }, 2) setTimeout(() => { console.log(1) }, 1) setTimeout(() => { console.log(0) }, 0)
有人說結果應該是0,1,2
但正確結果是2,1,0。
因為setTimeout最低延遲是4ms,值得注意。
我的博客:http://blog.rnode.me
參考文章:
原文:Event Loop的規范和實現 地址:https://juejin.im/post/5a6155126fb9a01cb64edb45 原文:這一次,徹底弄懂 JavaScript 執行機制 地址:https://juejin.im/post/59e85eebf265da430d571f89 原文:JavaScript 運行機制詳解:再談Event Loop 地址:http://www.ruanyifeng.com/blog/2014/10/event-loop.html
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/98478.html
摘要:不過其實簡書文章評論里有很多大家的問題以及解答,對于進一步理解文中知識幫助很大的,算是有點可惜吧。不過也希望能夠對正在學習前端的你有一些小幫助。如果在閱讀中發現了一些錯誤,請在評論里告訴我,我會及時更改。 前端基礎進階(一):內存空間詳細圖解 前端基礎進階(二):執行上下文詳細圖解 前端基礎進階(三):變量對象詳解 前端基礎進階(四):詳細圖解作用域鏈與閉包 前端基礎進階(五):全方位...
摘要:之前文章詳細介紹了的使用,不了解的查看進階期。不同的引擎有不同的限制,核心限制在,有些引擎會拋出異常,有些不拋出異常但丟失多余參數。存儲的對象能動態增多和減少,并且可以存儲任何值。這邊采用方法來實現,拼成一個函數。 之前文章詳細介紹了 this 的使用,不了解的查看【進階3-1期】。 call() 和 apply() call() 方法調用一個函數, 其具有一個指定的 this 值和分...
摘要:使用指定的參數調用構造函數,并將綁定到新創建的對象。由構造函數返回的對象就是表達式的結果。情況返回以外的基本類型實例中只能訪問到構造函數中的屬性,和情況完全相反,結果相當于沒有返回值。 定義 new 運算符創建一個用戶定義的對象類型的實例或具有構造函數的內置對象的實例。 ——(來自于MDN) 舉個栗子 function Car(color) { this.color = co...
摘要:一棧數據結構與不同,中并沒有嚴格意義上區分棧內存與堆內存。引用數據類型的值是保存在堆內存中的對象。不允許直接訪問堆內存中的位置,因此我們不能直接操作對象的堆內存空間。為了更好的搞懂變量對象與堆內存,我們可以結合以下例子與圖解進行理解。 showImg(https://segmentfault.com/img/remote/1460000009784102?w=1240&h=683); ...
摘要:報文用于協議交互的信息被稱為報文。現在出現的各種首部字段及狀態碼稍后會闡述。狀態碼響應報文包含了多個范圍的內容使用。如果服務器無法響應范圍請求,則會返回狀態碼和完整的實體內容。 showImg(https://segmentfault.com/img/bVbthNL?w=900&h=500); http報文 用于HTTP協議交互的信息被稱為HTTP報文。請求端的http報文叫做請求報文...
閱讀 2115·2021-11-23 10:06
閱讀 3478·2021-11-11 16:54
閱讀 3346·2019-08-29 17:31
閱讀 3570·2019-08-29 17:05
閱讀 2172·2019-08-26 13:36
閱讀 2161·2019-08-26 12:17
閱讀 528·2019-08-26 12:12
閱讀 1674·2019-08-26 10:19