瀏覽器的內核是多線程的,它們在內核制控下相互配合以保持同步,一個瀏覽器至少實現三個常駐線程: javascript
javascript引擎是基於事件驅動單線程執行的,JS引擎一直等待着任務隊列中任務的到來,而後加以處理,瀏覽器不管何時都只有一個JS線程
在運行JS程序php
GUI渲染線程負責渲染瀏覽器界面,當頁面須要重繪(repaint)
或因爲某種操做引起的迴流(reflow)
時,該線程就會執行.可是,須要注意的是GUI渲染線程
與javascript引擎線程
是互斥的
,當js引擎
執行時,GUI線程
就會被掛起,GUI更新會被保存在一個隊列中,等待js引擎空閒時當即被執行.html
事件觸發線程,當一個事件被觸發時,該線程會把事件添加到待處理隊列的隊尾,等待JS引擎的處理。這些事件可來自JavaScript引擎當前執行的代碼塊如setTimeOut、也可來自瀏覽器內核的其餘線程如鼠標點擊、AJAX異步請求等,但因爲JS的單線程關係全部這些事件都得排隊等待JS引擎處理
。
參考:
JavaScript能否多線程? 深刻理解JavaScript定時機制java
到這裏, 就要說另外一個問題, js的異步問題
瀏覽器
在js中,咱們經常使用setTimeout(function(){},0)
的方式來處理js的異步.
炒個栗子多線程
console.log(1); setTimeout(function(){console.log(2)},0); console.log(3);
輸出: 1 , 3, 2
不信點我試試setTimeout(..)
並無把你的回調函數掛在事件循環隊列中。它所作的是設 定一個定時器。
當定時器到時後,環境會把你的回調函數放在事件隊列中,若是這時候事件循環中已經有 20 個項目了會怎樣呢?你的回調就會等待,定時器只能確保你的回調函數不會在指定的 時間間隔以前運行,但可能會在那個時刻運行,也可能在那以後運行,要根據事件隊列的 狀態而定(PS: 這就是形成定時器不許確的原因)。異步
setTimeout(..0)(hack)
進行異步調度,基本上它的意思就是把這個函數插入到當前事件循環隊列的結尾處
。函數
正常狀況下javascript都是按照順序執行的。可是咱們可能讓該語句後面的語句執行完再執行自己,先執行全部的同步再執行全部的異步.
炒個栗子spa
for(var i = 0;i < 3;i++){ setTimeout(function(){ alert('知乎'); },0) alert(i); }
點我看看
輸出: 0 1 2 知乎 知乎 知乎
,
setTimeout第二個參數爲0表示當即執行。當使用這個方法的時候,瀏覽器會另起一個線程,來執行setTimeout裏面的函數,而原有的線程繼續執行, 待原有線程結束後,在執行後面的線程(js單線程)。.net