瀏覽器的內核是多線程的,它們在內核制控下相互配合以保持同步,一個瀏覽器至少實現三個常駐線程:javascript引擎線程,GUI渲染線程,瀏覽器事件觸發線程。
javascript執行順序:http://bbs.html5cn.org/thread-80116-1-1.html
JS一定要放在Body的最底部么:http://www.html5cn.org/article-9333-1.html
淺談script標簽的defer和async:https://segmentfault.com/a/1190000006778717
1.javascript引擎是基於事件驅動單線程執行的,JS引擎一直等待着任務隊列中任務的到來,然后加以處理,瀏覽器無論什么時候都只有一個JS線程在運行JS程序。
2.GUI渲染線程負責渲染瀏覽器界面,當界面需要重繪(Repaint)或由於某種操作引發回流(reflow)時,該線程就會執行。但需要注意 GUI渲染線程與JS引擎是互斥的,當JS引擎執行時GUI線程會被掛起,GUI更新會被保存在一個隊列中等到JS引擎空閑時立即被執行。
3.事件觸發線程,當一個事件被觸發時該線程會把事件添加到待處理隊列的隊尾,等待JS引擎的處理。這些事件可來自JavaScript引擎當前執行的代碼塊如setTimeOut、也可來自瀏覽器內核的其他線程如鼠標點擊、AJAX異步請求等,但由於JS的單線程關系所有這些事件都得排隊等待JS引擎處理。
4.即使setTimeout為0,他也是等js引擎的代碼執行完之后才會插入到js引擎線程的最后執行。js的工作機制是:當線程中沒有執行任何同步代碼的前提下才會執行異步代碼,setTimeout是異步代碼,所以setTimeout只能等js空閑才會執行,但死循環是永遠不會空閑的,所以setTimeout也永遠不會執行。
例子:
<input type="text" value="a" name="input" onkeydown="console.log(this.value)">
<input type="text" value="a" name="input" onkeydown="var me=this;setTimeout(function(){console.log(me.value)},0)">
分析:第一個在keydown的時候,彈出來的是input里原來的value,而第2個在keydown的時候,卻能彈出更新后的value,就是因為setTimeout,雖然他的delay設置為0,幾乎是即時觸發,但還是被添加到了執行隊列后面,但就是這個過程,渲染已經完成了,當他回調函數執行時,輸出來的已經是更新后的value了。
