由一段代碼進(jìn)行正題:
console.log(1);
setTimeout(function(){
console.log(2)
},0);
console.log(3)
瀏覽器依次輸出1,3,2,而不是看上去的1,2,3;
JS是單線程語言:JS在同一時(shí)間只能做一件事。
任務(wù)隊(duì)列:分為同步任務(wù)和異步任務(wù)曲饱;任務(wù)隊(duì)列有執(zhí)行順序,同步任務(wù)第一時(shí)間執(zhí)行珠月,同步任務(wù)執(zhí)行完成后才能執(zhí)行異步任務(wù)扩淀;
for(var i=0;i<3;i++){
setTimeout(function(){
console.log(i)
},1000)
}
運(yùn)行上面的代碼,瀏覽器會(huì)輸出:3,3,3啤挎。
這段代碼的原理在于驻谆,循環(huán)第一次的時(shí)候,執(zhí)行setTimeout函數(shù)侵浸,但是因?yàn)閟etTimeout函數(shù)是異步任務(wù)旺韭,所以里面的語句都會(huì)被掛起不執(zhí)行,循環(huán)第二次及之后的循環(huán)都是如此掏觉。那么此時(shí)setTimeout函數(shù)被放入異步隊(duì)列区端,但是不執(zhí)行,只有當(dāng)這個(gè)異步時(shí)間到了規(guī)定的時(shí)間澳腹,函數(shù)體才會(huì)被執(zhí)行织盼。對(duì)于這個(gè)例子來說杨何,for循環(huán)執(zhí)行完畢,setTimeout函數(shù)依次被放入異步隊(duì)列沥邻,然后過了1秒或2秒后危虱,異步隊(duì)列中的函數(shù)開始執(zhí)行。
Event Loop:瀏覽器的JS引擎遇到setTimeout函數(shù)唐全,識(shí)別這是一個(gè)異步任務(wù)埃跷,它不會(huì)把它放在運(yùn)行棧中,它會(huì)把它拿走放進(jìn)邮利,拿走之后也不會(huì)立即放入異步隊(duì)列中弥雹,先保留住,同步任務(wù)執(zhí)行完后延届,到了setTimeout函數(shù)約定的時(shí)間剪勿,time模塊會(huì)把它放入異步隊(duì)列,瀏覽器同步任務(wù)執(zhí)行完了方庭,就會(huì)執(zhí)行這個(gè)任務(wù)厕吉,它執(zhí)行完后執(zhí)行棧又空了,此時(shí)瀏覽器又會(huì)監(jiān)聽異步隊(duì)列中是否有任務(wù)需要執(zhí)行械念,如果有就會(huì)再拿出來執(zhí)行头朱,如此循環(huán)的過程就是Event Loop。
開啟異步任務(wù)的條件:
setTimeout和setInerval
DOM事件
ES6中的Promise
瀏覽器假死現(xiàn)象的原理也是因?yàn)镴S的單線程導(dǎo)致龄减,如果同步任務(wù)一直在處理髓窜,瀏覽器就會(huì)卡住,做不了其它操作