今天剛好在看setTimeout()的一個(gè)案例,在案例的解析中提到了setTimeout()和setInterval()的使用區(qū)別,但是比較理論,所以
決定自己也總結(jié)一下,寫(xiě)寫(xiě)例子幫助理解一下。
? ? ? ?首先是說(shuō)說(shuō)這兩個(gè)方法的具體時(shí)如何使用的。
1、setTimeout()方法
? ? ? 這個(gè)方法所有瀏覽器都支持,setTimeout( ) 是屬于 window 的 method, 但我們都是略去 window 這頂層物件名稱, 這是用來(lái)
設(shè)定一個(gè)時(shí)間, 時(shí)間到了, 就會(huì)執(zhí)行一個(gè)指定的 method。
? ? ? 定義和用法: setTimeout()方法用于在指定的毫秒數(shù)后調(diào)用函數(shù)或計(jì)算表達(dá)式。
? ? ? 語(yǔ)法: setTimeout(code,millisec)
? ? ? 參數(shù): code (必需):要調(diào)用的函數(shù)后要執(zhí)行的 JavaScript 代碼串。millisec(必需):在執(zhí)行代碼前需等待的毫秒數(shù)。 ?
?提示: setTimeout() 只執(zhí)行 code 一次。如果要多次調(diào)用,請(qǐng)使用 setInterval() 或者讓 code 自身再次調(diào)用 setTimeout()(即利用遞歸)。
? ? ? 看完了基本的語(yǔ)法,接下來(lái)我寫(xiě)一個(gè)很簡(jiǎn)單的例子說(shuō)明這個(gè)的使用方法。
代碼如下:
<!DOCTYPE html>
setTimeout()使用
請(qǐng)等待三秒!
setTimeout("alert('終于等到你了!')",3000)
? ? ? 當(dāng)我們打開(kāi)網(wǎng)頁(yè)3秒時(shí),就會(huì)彈出一個(gè)框。但是,只會(huì)彈出一次,因?yàn)?setTimeout()不會(huì)自動(dòng)重復(fù)執(zhí)行,是在載入后的延遲指定
時(shí)間去執(zhí)行一次表達(dá)式。
當(dāng)然,我們也可以讓setTimeout()執(zhí)行函數(shù),而且可以重復(fù)執(zhí)行多次(利用遞歸),而不是一次。
代碼如下:
<!DOCTYPE html>
varx =0;
functioncountSecond()
? ? ? ? {
x = x+1;
document.haorooms.haoroomsinput.value = x;
setTimeout("countSecond()",1000)
? ? ? ? }
? ? countSecond();
? ? ? ?實(shí)現(xiàn)的方法就是讓函數(shù)自身反復(fù)調(diào)用。
2、setInterval()方法
setInterval() 方法可按照指定的周期(以毫秒計(jì))來(lái)調(diào)用函數(shù)或計(jì)算表達(dá)式。setInterval() 方法會(huì)不停地調(diào)用函數(shù),直到?
clearInterval() 被調(diào)用或窗口被關(guān)閉。由 setInterval() 返回的 ID 值可用作 clearInterval() 方法的參數(shù)。
語(yǔ)法: setInterval(code,millisec[,"lang"])
? ? ?參數(shù): code 必需。要調(diào)用的函數(shù)或要執(zhí)行的代碼串。millisec 必須。周期性執(zhí)行或調(diào)用 code 之間的時(shí)間間隔,以毫秒計(jì)。
返回值: 一個(gè)可以傳遞給 Window.clearInterval() 從而取消對(duì) code 的周期性執(zhí)行的值。
? ? ?如果我們想要每隔3秒就彈出一個(gè)框要如何實(shí)現(xiàn)呢?
代碼如下:
<!DOCTYPE html>
Title
functiontest(){
this.name ="setInternal";
this.waitMes =function(){
varthat =this;
setInterval(function(){
? ? ? ? ? ? ? ? alert(that.name);
},3000);
? ? ? ? }
? ? }
varte =newtest();
? ? te.waitMes();
? ? ? ?setInterval() 從載入后,每隔指定的時(shí)間就執(zhí)行一次表達(dá)式。
3、區(qū)別
? ? ?通過(guò)上面可以看出,setTimeout和setinterval的最主要區(qū)別是:
? ? 1)setTimeout只運(yùn)行一次,也就是說(shuō)設(shè)定的時(shí)間到后就觸發(fā)運(yùn)行指定代碼,運(yùn)行完后即結(jié)束。如果運(yùn)行的代碼中再次運(yùn)行同樣
的setTimeout命令,則可循環(huán)運(yùn)行。(即 要循環(huán)運(yùn)行,需函數(shù)自身再次調(diào)用 setTimeout());而 setinterval是循環(huán)運(yùn)行的,即每
到設(shè)定時(shí)間間隔就觸發(fā)指定代碼。這是真正的定時(shí)器。
? ? 2)setinterval使用簡(jiǎn)單,而setTimeout則比較靈活,可以隨時(shí)退出循環(huán),而且可以設(shè)置為按不固定的時(shí)間間隔來(lái)運(yùn)行,比如第
一次1秒,第二次2秒,第三次3秒。
值得注意的是:
setTimeout(function(){
? ? console.log(1);
});
console.log(0);
這里,實(shí)際上,把setTimeout的第二個(gè)參數(shù)設(shè)置為0s,并不是立即執(zhí)行函數(shù)的意思,只是把函數(shù)放入異步隊(duì)列。瀏覽器先執(zhí)行完同步隊(duì)列里的任務(wù),才會(huì)去執(zhí)行異步隊(duì)列中的任務(wù)。
setInterval()原理與setTimeout(),也是講代碼放入異步隊(duì)列中。但是,setInterval()存在一個(gè)問(wèn)題,
使用setInterval()的問(wèn)題在于,定時(shí)器代碼可能在代碼再次被添加到隊(duì)列之前還沒(méi)有完成執(zhí)行,結(jié)果導(dǎo)致定時(shí)器代碼連續(xù)運(yùn)行好幾次,而之間沒(méi)有任何停頓。而javascript引擎對(duì)這個(gè)問(wèn)題的解決是:當(dāng)使用setInterval()時(shí),僅當(dāng)沒(méi)有該定時(shí)器的任何其他代碼實(shí)例時(shí),才將定時(shí)器代碼添加到隊(duì)列中。這確保了定時(shí)器代碼加入到隊(duì)列中的最小時(shí)間間隔為指定間隔。
但是,這樣會(huì)導(dǎo)致兩個(gè)問(wèn)題:1、某些間隔被跳過(guò);2、多個(gè)定時(shí)器的代碼執(zhí)行之間的間隔可能比預(yù)期的小。
兩者的工作原理:大家都知道,JavaScript是單線程執(zhí)行的,setTimeout和setInterval執(zhí)行原理其實(shí)也很簡(jiǎn)單。
setTimeout會(huì)在調(diào)用后的millisec時(shí)間間隔后往事件隊(duì)列里添加回調(diào)函數(shù),然后等待執(zhí)行。?
setInterval會(huì)按照第二個(gè)參數(shù)的周期時(shí)間周期性的往事件隊(duì)列添加回調(diào)函數(shù),然后等待執(zhí)行,這里的一個(gè)注意點(diǎn)是如果事件隊(duì)列里的回調(diào)函數(shù)還沒(méi)有執(zhí)行,不會(huì)重復(fù)添加。
注:html5規(guī)定setTimeout和setInterval的延遲時(shí)間最少為4ms. 所以setTimeout(function(){},0)其實(shí)是setTimeout(function(){}, 4)。
如果上面代碼中的onclick事件處理程序執(zhí)行了300ms,那么定時(shí)器的代碼至少要在定時(shí)器設(shè)置之后的300ms后才會(huì)被執(zhí)行。隊(duì)列中所有的代碼都要等到j(luò)avascript進(jìn)程空閑之后才能執(zhí)行,而不管它們是如何添加到隊(duì)列中的。如下圖:

如圖所示,盡管在255ms處添加了定時(shí)器代碼,但這時(shí)候還不能執(zhí)行,因?yàn)閛nclick事件處理程序仍在運(yùn)行。定時(shí)器代碼最早能執(zhí)行的時(shí)機(jī)是在300ms處,即onclick事件處理程序結(jié)束之后。
實(shí)際上,把setTimeout的第二個(gè)參數(shù)設(shè)置為0s,并不是立即執(zhí)行函數(shù)的意思,只是把函數(shù)放入異步隊(duì)列。瀏覽器先執(zhí)行完同步隊(duì)列里的任務(wù),才會(huì)去執(zhí)行異步隊(duì)列中的任務(wù)。
驗(yàn)證例子:
例一:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鳥(niǎo)教程(runoob.com)</title>
<script>
(function(){
var i=0;
? ? setTimeout(function(){
? ? ? ? document.getElementById("demo").innerHTML=1233131123;
},2500)
setInterval(function(){
i++;
document.getElementById("demo").innerHTML=i;
},1000)
})()
</script>
</head>
<body>
<h1>我的第一個(gè) JavaScript 程序</h1>
<p id="demo">這是一個(gè)段落</p>
<button type="button" onclick="displayDate()">顯示日期</button>
</body>
</html>
此代碼結(jié)果顯示先后順序:
1(1s)、2(2s)、1233131123(2.5s)、3(3s)、4(4s)........
原理分析:

例二:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鳥(niǎo)教程(runoob.com)</title>
<script>
(function(){
var i=0;
setInterval(function(){
i++;
document.getElementById("demo").innerHTML=i;
setTimeout(function(){
? ? ? ? document.getElementById("demo").innerHTML=1233131123;
},2500)
},1000)
})()
</script>
</head>
<body>
<h1>我的第一個(gè) JavaScript 程序</h1>
<p id="demo">這是一個(gè)段落</p>
<button type="button" onclick="displayDate()">顯示日期</button>
</body>
</html>
效果及分析:
