面試問到了這個,之前只了解JavaScript的對象原型椒振,作用域這些昭伸,這回認(rèn)真理解一下單線程的執(zhí)行邏輯。
對于JS來說澎迎,語言一大特點(diǎn)就是單線程庐杨,這是在原語言設(shè)計為dom操作腳本時因為復(fù)雜的同步問題設(shè)計成的。
為了避免dom操作沖突的復(fù)雜性嗡善,js單線程變成了一大特征不會改變辑莫。而單線程就意味著所有任務(wù)需要排隊,前一個任務(wù)完成時再執(zhí)行后面的罩引。
ps:對象被分配在一個堆中,即用以表示一個大部分非結(jié)構(gòu)化的內(nèi)存區(qū)域枝笨,占用內(nèi)存但不分擔(dān)任務(wù)只做存儲袁铐。
runtime
所有任務(wù)分成同步sync和異步任務(wù)async,所有同步任務(wù)直接在主線程上執(zhí)行横浑,形成執(zhí)行棧剔桨。
每一個棧的楨執(zhí)行完才會執(zhí)行下一楨,執(zhí)行時需要調(diào)用函數(shù)時徙融,直接在該處使調(diào)用函數(shù)進(jìn)棧洒缀,于棧頂立即執(zhí)行。
而如setTimeout和ajax等,則相當(dāng)于同步執(zhí)行時树绩,添加一個異步任務(wù)到異步任務(wù)隊列中萨脑。
所有異步隊列在同步,即執(zhí)行棧饺饭,執(zhí)行完后再按結(jié)果完成狀態(tài)和先后進(jìn)入順序的開始執(zhí)行渤早。
異步隊列子任務(wù)被吊起時,相當(dāng)于執(zhí)行同步任務(wù)一樣瘫俊,調(diào)入執(zhí)行棧鹊杖,執(zhí)行可執(zhí)行同步函數(shù)和調(diào)用函數(shù),需要時再吊起異步任務(wù)到異步隊列中扛芽。
主進(jìn)程不斷執(zhí)行上述循環(huán)骂蓖,可能這就是事件循環(huán)的意思吧。
特點(diǎn)
(function() {
console.log('this is the start');
setTimeout(function cb() {
console.log('this is a msg from call back');
});
// for (var i = 9999; i >= 0; i--) {
console.log('this is just a message');
// }
setTimeout(function cb1() {
console.log('this is a msg from call back1');
}, 0);
console.log('this is the end');
})();
上面的例子就能看出執(zhí)行順序了川尖,即使是0延遲的setTimeout涯竟,他還是會等到前面的所有同步任務(wù)執(zhí)行完再執(zhí)行,即使同步任務(wù)中可能有
執(zhí)行時間超久的(如:for)空厌,他還是會等候同步棧執(zhí)行完再執(zhí)行異步隊列相關(guān)庐船,這就是Js的其中一個特點(diǎn)"執(zhí)行至完成"。
"執(zhí)行至完成"的意思就是嘲更,只有前面的同步任務(wù)筐钟,函數(shù)執(zhí)行完,才會執(zhí)行后面的赋朦,他不能被搶占篓冲。因此存在缺點(diǎn),一個同步任務(wù)或者函數(shù)
如果長時間掛著的話宠哄,是不能執(zhí)行其他交互函數(shù)的壹将,整個頁面或者交互就僵住了。毛嫉。诽俯。所以同步不應(yīng)該寫太長久的邏輯或者可以剪開,或者分成異步寫
或者寫時間限制catch超時承粤。
有了這個特點(diǎn)暴区,就可以讓js無堵塞,只進(jìn)行快速的同步任務(wù)辛臊,不會因為交互的異步堵塞仙粱,可以在等待響應(yīng)的同時執(zhí)行其他項任務(wù)。