JS中的setTimeout()函數(shù)
1、setTimeout() 方法
setTimeout() 方法用于在指定的毫秒數(shù)后調(diào)用函數(shù)或執(zhí)行表達(dá)式。返回一個(gè) ID(數(shù)字),可以將這個(gè)ID傳遞給 clearTimeout() 來(lái)取消執(zhí)行。
setTimeout(code, milliseconds, param1, param2, ...) setTimeout(function, milliseconds, param1, param2, ...) //code|function:必需。要調(diào)用一個(gè)代碼串,也可以是一個(gè)函數(shù)。 第三個(gè)及之后的參數(shù):可選,傳給setTimeout函數(shù)里面的函數(shù)作為他的參數(shù)(IE9 及其更早版本不支持第三個(gè)及之后的參數(shù))。
setTimeout(function(){ alert("Hello"); }, 3000); //三秒之后執(zhí)行函數(shù) setTimeout(alertFunc, 3000); //三秒之后調(diào)用alertFunc函數(shù) function alertFunc() { alert("Hello!"); }
1.1、使用 clearTimeout() 方法阻止函數(shù)的執(zhí)行
在setTimeout() 里面的函數(shù)執(zhí)行之前可以使用 clearTimeout() 方法阻止 setTimeout() 里面的函數(shù)執(zhí)行。
1.2、setTimeout() 的三個(gè)及之后的參數(shù)
第三個(gè)及之后的參數(shù)是setTimeout()函數(shù)的可選參數(shù),是作為參數(shù)傳給 setTimeout() 方法里面的匿名函數(shù)或者調(diào)用的函數(shù),IE9 及其更早版本不支持第三個(gè)及之后的參數(shù)。
//IE9 及其更早版本不支持第三個(gè)及之后的參數(shù) var alertFunc = function(a,b){console.log(a,b)}; setTimeout(alertFunc, 2000, "Runoob", "Google"); //另外一種寫(xiě)法達(dá)到同樣目的 setTimeout(function(){ alertFunc("Runoob", "Google"); }, 2000);
2、當(dāng)settimeout()的時(shí)間參數(shù)為0時(shí)
setTimeout(function(){ console.log(1); }, 0); console.log(2); console.log(3); //輸出: 2 3 1
JS 是單線程的,單線程就意味著所有任務(wù)需要排隊(duì),前一個(gè)任務(wù)結(jié)束,才會(huì)執(zhí)行后一個(gè)任務(wù)。如果前一個(gè)任務(wù)耗時(shí)很長(zhǎng),后一個(gè)任務(wù)就不得不一直等著。在JS中同時(shí)維護(hù)著一個(gè)任務(wù)隊(duì)列,上面代碼中當(dāng)執(zhí)行遇到setTimeout(fn,millisec)時(shí),會(huì)把fn這個(gè)函數(shù)放在任務(wù)隊(duì)列中,當(dāng)JS引擎線程空閑時(shí)并達(dá)到millisec指定的時(shí)間時(shí),才會(huì)把fn放到j(luò)s引擎線程中執(zhí)行。
setTimeout()只是將事件插入了"任務(wù)隊(duì)列",必須等到當(dāng)前代碼(執(zhí)行棧)執(zhí)行完,主線程才會(huì)去執(zhí)行它指定的回調(diào)函數(shù)。要是當(dāng)前代碼耗時(shí)很長(zhǎng),有可能要等很久,所以并沒(méi)有辦法保證,回調(diào)函數(shù)一定會(huì)在setTimeout()指定的時(shí)間執(zhí)行。
3、解決在循環(huán)中setTimeout()函數(shù)輸出問(wèn)題
經(jīng)典問(wèn)題:
在for循環(huán)中使用 var 聲明變量是全局變量,當(dāng)for循環(huán)執(zhí)行完畢,此時(shí)的 i 是5。再經(jīng)過(guò)一秒鐘后分別調(diào)用setTimeout函數(shù),輸出的 i 都是全局作用域中的 i ,即5。
for(var i=0; i<5; i++){ setTimeout(() => { console.log(i); }, 1000); }
3.1、使用 let 關(guān)鍵字解決
let 關(guān)鍵字使每一次for循環(huán)中都有一個(gè)獨(dú)立作用域中的 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的執(zhí)行順序
setTimeout(function () { console.log('定時(shí)器開(kāi)始啦') }); new Promise(function (resolve) { console.log('馬上執(zhí)行for循環(huán)啦'); for (var i = 0; i < 10000; i++) { i == 99 && resolve(); } }).then(function () { console.log('執(zhí)行then函數(shù)啦') }); console.log('代碼執(zhí)行結(jié)束'); //輸出:馬上執(zhí)行for循環(huán)啦 代碼執(zhí)行結(jié)束 執(zhí)行then函數(shù)啦 定時(shí)器開(kāi)始啦

浙公網(wǎng)安備 33010602011771號(hào)