您好,登錄后才能下訂單哦!
前言
我們知道JS是一個單線程的語言,而且其運行機制比較特殊。
下面我們通過settimeout的幾個示例來展現javascript的運行機制的特殊點
示例1
console.log(1); setTimeout(function(){ console.log(2); },0); console.log(3); // 打印出 1 3 2
示例2
console.log('1'); setTimeout(function(){ console.log('2'); },0); while(1){} // 打印出1,然后瀏覽器卡死,不會打印出2
javascript會先把需要運行的內容放到任務隊列中
但是如果遇到settimeout,會認為這是個異步任務,會先放到異步隊列中
瀏覽器會先執行同步任務,等到同步任務執行完之后,再查看異步隊列
如果異步隊列中的任務的執行時機到了,瀏覽器就會把任務放到同步隊列中去。
即:
異步任務一定在同步任務之后執行。
示例3
for(var i = 0; i < 4; i++){ setTimeout(function() { console.log(i); }, 1000); } // 打印 4 4 4 4
為什么打印出的是4 4 4 4呢?
因為瀏覽器會先執行for循環
每執行一次for循環,都把一個settimeout壓入異步隊列
1000毫秒之后,執行settimeout里的方法的時候,i的值已經是4了。
如果要打印0 1 2 3怎么辦呢?
利用閉包的特性,把i緩存到一個temp值里
for(var i = 0; i < 4; i++){ (function(temp){ setTimeout(function() { console.log(temp); }, 1000); })(i); } // 打印 0 1 2 3
這樣做等于是每一次for循環都新建了一個匿名函數,i的值被存入了這個匿名函數的內存里。
理解了閉包的同學一定可以理解這一點。
示例4
我們知道ES6引入了新的關鍵字let
在這里,let有一個新的特性
for(let i = 0; i < 4; i ++){ setTimeout(function(){ console.log(i); }, 1000); } // 打印 0 1 2 3
示例4與示例3只有var和let這個地方有區別,但是打印出來的結果卻完全不同
這是因為let是一個塊級作用域
let定義的i,對于每一個for循環的執行來說都是一個全新的i(使用不同的內存地址)
所以打印的時候可以得到0 1 2 3
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對億速云的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。