setInterval(function,milliseconds,param1,param2,...)
code/function必需。要調(diào)用一個代碼串,也可以是一個函數(shù)。
milliseconds必須。周期性執(zhí)行或調(diào)用 code/function 之間的時間間隔,以毫秒計。
param1, param2, ...可選。 傳給執(zhí)行函數(shù)的其他參數(shù)(IE9 及其更早版本不支持該參數(shù))。
setInterval(function(){alert("Hello")},3000);
clearInterval() 方法用于停止 setInterval() 方法執(zhí)行的函數(shù)代碼
myVar=setInterval("javascript function",milliseconds);
setTimeout(code, millisec, args);
//code必需。要調(diào)用的函數(shù)后要執(zhí)行的 JavaScript 代碼串。
//millisec必需。在執(zhí)行代碼前需等待的毫秒數(shù)。
//args可選。 傳給執(zhí)行函數(shù)的其他參數(shù)
myVar=setTimeout(alertFunc,2000,"Runoob","Google");
1、setTimeout原理
varstart?=newDate();
varend?=?0;
setTimeout(function()?{??console.log(newDate()?-?start);?},?500);
while(newDate()?-?start?<=?1000)?{}
打印結(jié)果 1003
這是因為 JavaScript是單線程執(zhí)行的。也就是說,在任何時間點,有且只有一個線程在運行JavaScript程序,無法同一時候運行多段代碼。
雖然setTimeout的延時時間是500毫秒,可是由于while循環(huán)的存在,只有當(dāng)間隔時間大于1000毫秒時,才會跳出while循環(huán),也就是說,在1000毫秒之前,while循環(huán)都在占據(jù)著JavaScript線程。也就是說,只有等待跳出while后,線程才會空閑下來,才會去執(zhí)行之前定義的setTimeout。
最后 ,我們可以總結(jié)出,setTimeout只能保證在指定的時間后將任務(wù)(需要執(zhí)行的函數(shù))插入任務(wù)隊列中等候,但是不保證這個任務(wù)在什么時候執(zhí)行。一旦執(zhí)行javascript的線程空閑出來,自行從隊列中取出任務(wù)然后執(zhí)行它。
因為javascript線程并沒有因為什么耗時操作而阻塞,所以可以很快地取出排隊隊列中的任務(wù)然后執(zhí)行它,也是這種隊列機制,給我們制造一個異步執(zhí)行的假象。
瀏覽器下的javascript
JavaScript引擎是基于事件驅(qū)動單線程執(zhí)行的,JavaScript引擎一直等待著任務(wù)隊列中任務(wù)的到來,然后加以處理,瀏覽器無論什么時候都只有一個JavaScript線程在運行JavaScript程序。
GUI渲染線程負責(zé)渲染瀏覽器界面,當(dāng)界面需要重繪(Repaint)或由于某種操作引發(fā)回流(Reflow)時,該線程就會執(zhí)行。但需要注意,GUI渲染線程與JavaScript引擎是互斥的,當(dāng)JavaScript引擎執(zhí)行時GUI線程會被掛起,GUI更新會被保存在一個隊列中等到JavaScript引擎空閑時立即被執(zhí)行。
事件觸發(fā)線程,當(dāng)一個事件被觸發(fā)時,該線程會把事件添加到待處理隊列的隊尾,等待JavaScript引擎的處理。這些事件可來自JavaScript引擎當(dāng)前執(zhí)行的代碼塊如setTimeout、也可來自瀏覽器內(nèi)核的其他線程如鼠標點擊、Ajax異步請求等,但由于JavaScript的單線程關(guān)系,所有這些事件都得排隊等待JavaScript引擎處理(當(dāng)線程中沒有執(zhí)行任何同步代碼的前提下才會執(zhí)行異步代碼)。
2、setTimeout的好搭檔“0”
setTimeout(function(){
// statement
},0);
本意是立刻執(zhí)行調(diào)用函數(shù),但事實上,上面的代碼并不是立即執(zhí)行的,這是因為setTimeout有一個最小執(zhí)行時間,當(dāng)指定的時間小于該時間時,瀏覽器會用最小允許的時間作為setTimeout的時間間隔,也就是說即使我們把setTimeout的延遲時間設(shè)置為0,被調(diào)用的程序也沒有馬上啟動。
不同的瀏覽器實際情況不同,IE8和更早的IE的時間精確度是15.6ms。不過,隨著HTML5的出現(xiàn),在高級版本的瀏覽器(Chrome、ie9+等),定義的最小時間間隔是不得低于4毫秒,如果低于這個值,就會自動增加,并且在2010年及之后發(fā)布的瀏覽器中采取一致。
所以說,當(dāng)我們寫為 setTimeout(fn,0) 的時候,實際是實現(xiàn)插隊操作,要求瀏覽器“盡可能快”的進行回調(diào),但是實際能多快就完全取決于瀏覽器了。
那setTimeout(fn, 0)有什么用處呢?其實用處就在于我們可以改變?nèi)蝿?wù)的執(zhí)行順序!因為瀏覽器會在執(zhí)行完當(dāng)前任務(wù)隊列中的任務(wù),再執(zhí)行setTimeout隊列中積累的的任務(wù)。
通過設(shè)置任務(wù)在延遲到0s后執(zhí)行,就能改變?nèi)蝿?wù)執(zhí)行的先后順序,延遲該任務(wù)發(fā)生,使之異步執(zhí)行。
來看一個網(wǎng)上很流行的例子:
document.querySelector('#one input').onkeydown=function(){
document.querySelector('#one span').innerHTML=this.value;
};
document.querySelector('#second input').onkeydown=function(){
setTimeout(function(){
document.querySelector('#second span').innerHTML=document.querySelector('#second input').value;},0);
};
keydown:用戶在鍵盤上按下某按鍵是發(fā)生。一直按著某按鍵則會不斷觸發(fā)(opera瀏覽器除外)。
keypress:用戶按下一個按鍵,并產(chǎn)生一個字符時發(fā)生(也就是不管類似shift、alt、ctrl之類的鍵,就是說用戶按了一個能在屏幕上輸出字符的按鍵keypress事件才會觸發(fā))。一直按著某按鍵則會不斷觸發(fā)。
keyup:用戶釋放某一個按鍵是觸發(fā)。
當(dāng)你往兩個表單輸入內(nèi)容時,你會發(fā)現(xiàn)未使用setTimeout函數(shù)的只會獲取到輸入前的內(nèi)容,而使用setTimeout函數(shù)的則會獲取到輸入的內(nèi)容。
這是為什么呢?
因為當(dāng)按下按鍵的時候,JavaScript 引擎需要執(zhí)行 keydown 的事件處理程序,然后更新文本框的 value 值,這兩個任務(wù)也需要按順序來,事件處理程序執(zhí)行時,更新 value值(是在keypress后)的任務(wù)則進入隊列等待,所以我們在 keydown 的事件處理程序里是無法得到更新后的value的,而利用 setTimeout(fn, 0),我們把取 value 的操作放入隊列,放在更新 value 值以后,這樣便可獲取出文本框的值。
未使用setTimeout函數(shù),執(zhí)行順序是:onkeydown => onkeypress => onkeyup
使用setTimeout函數(shù),執(zhí)行順序是:onkeydown => onkeypress => function => onkeyup
雖然我們可以使用keyup來替代keydown,不過有一些問題,那就是長按時,keyup并不會觸發(fā)。
3、setTimeout的一些秘密
3.1 setTimeout中回調(diào)函數(shù)的this
由于setTimeout() 方法是瀏覽器 window 對象提供的,因此第一個參數(shù)函數(shù)中的this其實是指向window對象,這跟變量的作用域有關(guān)。
vara=1;
varobj={
a:2,
test:function(){
setTimeout(function(){
console.log(this.a);
},0);
}
};
obj.test();// ?1
不過我們可以通過使用bind()方法來改變setTimeout回調(diào)函數(shù)里的this
vara=1;
varobj={
a:2,
test:function(){
setTimeout(function(){
console.log(this.a);
}.bind(this),0);
}
};
obj.test();// ?2
3.2 setTimeout不止兩個參數(shù)
我們都知道,setTimeout的第一個參數(shù)是要執(zhí)行的回調(diào)函數(shù),第二個參數(shù)是延遲時間(如果省略,會由瀏覽器自動設(shè)置。在IE,F(xiàn)ireFox中,第一次配可能給個很大的數(shù)字,100ms上下,往后會縮小到最小時間間隔,Safari,chrome,opera則多為10ms上下。)
其實,setTimeout可以傳入第三個參數(shù)、第四個參數(shù)….,它們表示神馬呢?其實是用來表示第一個參數(shù)(回調(diào)函數(shù))傳入的參數(shù)。
setTimeout(function(a,b){
console.log(a);// 3
console.log(b);// 4
},0,3,4);
請除setTimeout
myVar=setTimeout("javascript function",milliseconds);