能夠理解爲:只有在JS線程中沒有任何同步代碼要執行的前提下才會執行異步代碼javascript
首先明確,瀏覽器的內核是多線程的,它們在內核制控下相互配合以保持同步,一個瀏覽器至少實現三個常駐線程:java
JavaScript 引擎是單線程運行的,瀏覽器不管在何時都只且只有一個線程在運行JavaScript程序瀏覽器
在具有了上述理論基礎以後,咱們對如下幾個實例進行分析:多線程
===========================================閉包
var t = true; window.setTimeout(function (){ t = false; },1000); while (t){} alert('end');
運行結果:程序陷入死循環,t = false
得不到執行,所以 alert('end')
不會執行。
解析:異步
===========================================函數
var start = new Date(); setTimeout(function(){ var end = new Date(); console.log("Time elapsed: ", end - start, "ms"); }, 500); while (new Date - start <= 1000){}
運行結果:"Time elapsed: 1035 ms" (這裏的1035不許確 可是必定是大於1000的)
解析:oop
===========================================this
for(var i=0;i<10;i++){ setTimeout(function() { console.log(i); }, 0); }
運行結果:輸出10個10
解析:JS單線程 setTimeout 異步代碼 任務隊列
問:如何修改可使上述代碼輸出 0123456789
自執行函數 或 使用ES6中的let關鍵字線程
// 自執行函數 造成閉包 記憶其被建立時的環境 for(var i=0;i<10;i++){ setTimeout((function() { console.log(i); })(), 0); }
如今咱們瞭解了setTimeout函數執行的原理,那麼它有什麼做用呢?
setTimeout函數增長了Javascript函數調用的靈活性,爲函數執行順序的調度提供極大便利。
簡言之,改變順序,這正是setTimeout(0)的做用。
使用場景示例:
<input type="text" onkeydown="show(this.value)"> <div></div> <script type="text/javascript"> function show(val) { document.getElementsByTagName('div')[0].innerHTML = val; } </script>
這裏綁定了 keydown 事件,意圖是當用戶在文本框裏輸入字符時,將輸入的內容實時地在 <div> 中顯示出來。可是實際效果並不是如此,能夠發現,每按下一個字符時,<div> 中只能顯示出以前的內容,沒法獲得當前的字符。
修改代碼:
<input type="text" onkeydown="var self=this; setTimeout(function(){show(self.value)}, 0)"> <div></div> <script type="text/javascript"> function show(val) { document.getElementsByTagName('div')[0].innerHTML = val; } </script>
這段代碼使用setTimeout(0)就能夠實現須要的效果了。
這裏其實涉及2個任務,1個是將鍵盤輸入的字符回寫到輸入框中,一個是獲取文本框的值將其寫入div中。第一個是瀏覽器自身的默認行爲,一個是咱們本身編寫的代碼。很顯然,必需要先讓瀏覽器將字符回寫到文本框,而後咱們才能獲取其內容寫到div中。改變順序,這正是setTimeout(0)的做用。
其餘應用場景:有時候,加載一些廣告的時候,咱們用setTimeout實現異步,好讓廣告不會阻塞咱們頁面的渲染。