1、 js引擎是單線程的還是多線程的誓琼?
? ? ? ? ? 從表面看來,setTimeout()肴捉、ajax異步請求腹侣、回調(diào)函數(shù)這些js中比較重要的特性看起來是多線程的,但是js引擎卻是 單線程 的齿穗。時至今日傲隶,HTML5中已經(jīng)提出了web worker標(biāo)準(zhǔn),允許js腳本去創(chuàng)造多個線程窃页,但是這些線程中只有一個主線程跺株,而且其他線程都受主線程的控制,所以脖卖,js的本質(zhì)依然是單線程乒省。但是我們都知道,單線程只能在同一時間處理一件事務(wù)畦木,那么這一定會有效率差的問題袖扛,因?yàn)椋?dāng)前事務(wù)的處理十籍,一定會堵塞事件隊列中的其他事務(wù)的執(zhí)行蛆封。而某些耗時的io操作,比如鍵盤輸入勾栗,比如ajax于是js引入了 異步 的解決方案惨篱,采用了 event loop 機(jī)制去將耗時的io操作放入事件隊列(所謂 事件隊列 ,就是只有前一個事件執(zhí)行完畢围俘,后一個事件才會繼續(xù)執(zhí)行)中去妒蛇,先去執(zhí)行下一個事務(wù)操作机断,而那些放入到隊列中的耗時的io操作(比如ajax)在執(zhí)行完畢之后,javascript會將異步方法的執(zhí)行結(jié)果放入到事件隊列中绣夺,等待執(zhí)行。
? ? ? ? ?而正是因?yàn)閖avascript的非阻塞的io事件處理模型欢揖,node才最終選擇了js陶耍,大大推動了js在服務(wù)端的發(fā)展。
2她混、瀏覽器是多線程的
? ? ?js引擎線程只是瀏覽器中的一個線程烈钞。通常瀏覽器會有三個線程:js引擎線程、GUI線程(用于渲染視圖)坤按、瀏覽器時間觸發(fā)線程(用于用戶對瀏覽器的控制交互)
3毯欣、js引擎采用單線程機(jī)制,這和js的誕生有關(guān):
? ? ? js被創(chuàng)造出來用于實(shí)現(xiàn)操作瀏覽器html中的DOM樹臭脓、CSS樣式樹以及實(shí)現(xiàn)界面中用戶與html中DOM的動態(tài)交互酗钞,那么問題來了,假如js是多線程執(zhí)行来累,那么很可能出現(xiàn)同一時刻有兩個線程在操作同一個UI DOM元素砚作,并且假如一個線程用于給DOM元素添加樣式,而另一個線程用于刪除DOM元素嘹锁。這時候葫录,這個DOM就成為了 臨界資源,瀏覽器就無法去裁決究竟以哪一個線程的操作為準(zhǔn)领猾。雖然米同,我們也可以實(shí)現(xiàn)某些? 鎖 來規(guī)避這種線程操作互斥的情況,但是這一定會給js開發(fā)帶來更大的復(fù)雜性摔竿。所以js最終采用單線程機(jī)制面粮。
4、setTimeout()
? ? ? setTimeout()方法有兩個參數(shù)拯坟,第一個參數(shù)為一個 函數(shù)但金,第二個參數(shù)是一個時間。
? ? ?首先看這個代碼: ? setTimeout(function hello(),1000);
? ? ?內(nèi)部的運(yùn)行順序:在js引擎執(zhí)行完該行js代碼之后郁季,會在1000毫秒之后會把hello()這個函數(shù)放入到事件隊列中冷溃。等到事件隊列中排在hello()之前的任務(wù)執(zhí)行完畢后,hello()得到執(zhí)行梦裂。所以setTimeout方法中設(shè)置的時間為1000毫秒似枕,只是說明在setTimeout()方法運(yùn)行之后的1000毫秒時,把setTimeout方法的第一個參數(shù):hello()函數(shù)放入到事件隊列中準(zhǔn)備執(zhí)行年柠。注意凿歼,這里是準(zhǔn)備執(zhí)行,而不是立即執(zhí)行。所以答憔,在setTimeout()方法執(zhí)行后味赃,到hello()執(zhí)行的 ?時間差 總是大于1000毫秒的。