參考:
https://blog.csdn.net/u012925833/article/details/89306184
詳解JavaScript中的Event Loop(事件循環(huán))機制
1.為什么JS是單線程的?
為了保證程序的一致性,避免多個線程對同一個DOM元素 既刪除又添加事件。
2.JS是如何實現(xiàn)非阻塞的呢?
執(zhí)行異步任務(wù)時,不是一直等待返回結(jié)果,而是會掛起這個任務(wù),在任務(wù)返回結(jié)果后再按一定的規(guī)則去執(zhí)行相應(yīng)的回調(diào)
3.異步任務(wù)是有類型,宏任務(wù)和微任務(wù)。遇到異步任務(wù)后,會將其分別放到宏任務(wù)隊列和微任務(wù)隊列中。在當(dāng)前執(zhí)行棧中的同步代碼運行完之后,先執(zhí)行微任務(wù)隊列中的任務(wù),再執(zhí)行宏任務(wù)隊列。在執(zhí)行微任務(wù)隊列中的任務(wù)時,如果又遇到微任務(wù),會放到微任務(wù)隊列中的隊尾,遇到宏任務(wù)時,就放到宏任務(wù)隊列中的隊尾。
如果在宏任務(wù)隊列里又遇到微任務(wù),說是在執(zhí)行完當(dāng)前宏任務(wù)之后,會檢查微任務(wù)隊列執(zhí)行微任務(wù),微任務(wù)隊列清空之后,再重新執(zhí)行剩下的宏任務(wù)隊列。
后續(xù)的宏任務(wù)和該微任務(wù)的執(zhí)行順序不定,有時宏任務(wù)先執(zhí)行,有時微任務(wù)先執(zhí)行。
setTimeout 、setTimeout 是宏任務(wù)
Promise 、 async await、MutaionObserver 是微任務(wù)
- 為什么要了解事件循環(huán)的執(zhí)行順序?
合理的使用各種延遲事件的方法,有助于代碼更好的按照其優(yōu)先級去執(zhí)行。
5.當(dāng)前執(zhí)行?!⑷蝿?wù)隊列——宏任務(wù)隊列 。執(zhí)行隊列里的任務(wù)時,是在當(dāng)前執(zhí)行棧中執(zhí)行的,執(zhí)行之后又一次檢查兩個隊列。
6.當(dāng)前執(zhí)行棧執(zhí)行完畢時會立刻先處理所有微任務(wù)隊列中的事件,然后再去宏任務(wù)隊列中取出一個事件。同一次事件循環(huán)中,微任務(wù)永遠(yuǎn)在宏任務(wù)之前執(zhí)行。
有多次事件循環(huán)嗎?以什么判斷本次事件循環(huán)結(jié)束下一次事件循環(huán)開始了呢?
7.為什么有些瀏覽器會在執(zhí)行順序上有不同的表現(xiàn)呢?
其實是因為“將promise作為task還是microtask引起的”,不同瀏覽器的解析不一樣
下面代碼的打印順序是如何的?
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,
//a 的初始值為true和false時,執(zhí)行結(jié)果分別是什么
var a = false;
setTimeout(function(){
a = !a;
console.log(a)
}, 100)
while(a){
console.log('while執(zhí)行了')
}