1、setTimeout() 方法
setTimeout() 方法用於在指定的毫秒數后調用函數或執行表達式。返回一個 ID(數字),可以將這個ID傳遞給 clearTimeout() 來取消執行。
setTimeout(code, milliseconds, param1, param2, ...) setTimeout(function, milliseconds, param1, param2, ...) //code|function:必需。要調用一個代碼串,也可以是一個函數。 第三個及之后的參數:可選,傳給setTimeout函數里面的函數作為他的參數(IE9 及其更早版本不支持第三個及之后的參數)。
setTimeout(function(){ alert("Hello"); }, 3000); //三秒之后執行函數 setTimeout(alertFunc, 3000); //三秒之后調用alertFunc函數 function alertFunc() { alert("Hello!"); }
1.1、使用 clearTimeout() 方法阻止函數的執行
在setTimeout() 里面的函數執行之前可以使用 clearTimeout() 方法阻止 setTimeout() 里面的函數執行。
1.2、setTimeout() 的三個及之后的參數
第三個及之后的參數是setTimeout()函數的可選參數,是作為參數傳給 setTimeout() 方法里面的匿名函數或者調用的函數,IE9 及其更早版本不支持第三個及之后的參數。
//IE9 及其更早版本不支持第三個及之后的參數 var alertFunc = function(a,b){console.log(a,b)}; setTimeout(alertFunc, 2000, "Runoob", "Google"); //另外一種寫法達到同樣目的 setTimeout(function(){ alertFunc("Runoob", "Google"); }, 2000);
2、當settimeout()的時間參數為0時
setTimeout(function(){ console.log(1); }, 0); console.log(2); console.log(3); //輸出: 2 3 1
JS 是單線程的,單線程就意味着所有任務需要排隊,前一個任務結束,才會執行后一個任務。如果前一個任務耗時很長,后一個任務就不得不一直等着。在JS中同時維護着一個任務隊列,上面代碼中當執行遇到setTimeout(fn,millisec)時,會把fn這個函數放在任務隊列中,當JS引擎線程空閑時並達到millisec指定的時間時,才會把fn放到js引擎線程中執行。
setTimeout()只是將事件插入了"任務隊列",必須等到當前代碼(執行棧)執行完,主線程才會去執行它指定的回調函數。要是當前代碼耗時很長,有可能要等很久,所以並沒有辦法保證,回調函數一定會在setTimeout()
指定的時間執行。
3、解決在循環中setTimeout()函數輸出問題
經典問題:
在for循環中使用 var 聲明變量是全局變量,當for循環執行完畢,此時的 i 是5。再經過一秒鍾后分別調用setTimeout函數,輸出的 i 都是全局作用域中的 i ,即5。
for(var i=0; i<5; i++){ setTimeout(() => { console.log(i); }, 1000); }
3.1、使用 let 關鍵字解決
let 關鍵字使每一次for循環中都有一個獨立作用域中的 i ,互不干擾,所以輸出的都是各自作用域中的 i,而不是全局作用域中的 i
for(let i=0; i<5; i++){ setTimeout(() => { console.log(i); }, 1000); } //輸出 0 1 2 3 4
3.2、使用閉包解決
for(var i=0; i<5; i++){ (function(j){ setTimeout(() => { console.log(j); }, 1000) })(i) } //輸出 0 1 2 3 4
4、setTimeout和promise的執行順序
setTimeout(function () { console.log('定時器開始啦') }); new Promise(function (resolve) { console.log('馬上執行for循環啦'); for (var i = 0; i < 10000; i++) { i == 99 && resolve(); } }).then(function () { console.log('執行then函數啦') }); console.log('代碼執行結束'); //輸出:馬上執行for循環啦 代碼執行結束 執行then函數啦 定時器開始啦