js中定時器setTimeout和setInterval兩種定時器
阿新 • • 發佈:2018-11-05
專案中,經常會用到定時器來實現資料實時更新、時間等,簡單總結一下:
Javascript中的定時器有兩種,setInterval和setTimeout,而定時器的作用就是延遲執行。
一、定時器的寫法
setInterval(expression,milliseconds);
setTimeout(expression,milliseconds);
上式中,expression既可以是字串,也可以是匿名函式,或者也可以是一個函式名。但是,函式名中不能傳參。第二個引數為延遲要執行的時間。
具體寫法如下:
(1)函式名,不帶引數
setInterval(test,1000); //1秒後執行
(2)字串,可以執行的程式碼
setInterval('test()',1000); //1秒後執行
(3)匿名函式
setInterval(function(){},1000); //1秒後執行
(4)呼叫函式
setInterval(test,1000); //立即執行
如果想要傳引數,可以自己定義一個函式,如下:
function test (str){
console.log(str);
}
setInterval(test(str),1000); //立即執行
注:setTimeout的用法一樣
二、定時器的清除
由於定時器在呼叫時,都會返回一個整形的數字,該數字代表定時器的序號,即第多少個定時器,所以定時器的清除要藉助於這個返回的數字。
定時器清除的方法:clearInterval(str)和clearTimeout(str)。
要清除定時器,就必須在用定時器的時候,定義一個變數來記錄定時器的返回值。如下:
var str = setInterval(test,1000);
setTimeout的用法也一樣。
注:有時候在寫的時候,還會習慣將清空的定時器的變數置空,這樣寫既可以釋放記憶體,也可以便於後邊程式碼的判斷。
三、定時器的執行機理
在工作或面試中,經常會遇到將‘定時器和JS的執行機制’結合起來的題。下面簡單介紹下:
定時器:延遲執行。
Javascript:單執行緒執行。
所以,在程式碼中遇到定時器時,定時器中要執行的程式碼,都要排在JS執行程式碼的後面,有如下幾種情況:
(1)第一種情況
程式碼:
列印結果:
(2)第二種情況
程式碼:
或
列印結果:
(3)第三種情況
程式碼:
列印結果:
由上述幾種情況可以斷定,程式碼執行順序:先執行完JS主執行緒程式碼後,再執行定時器延遲執行的程式碼。
變數作用域和定時器
- 變數提升
JS的直譯器在解釋JS程式碼的時候會首先將程式碼都掃描一遍,將其中的變數和函式的宣告提升到程式碼塊的頂部,所以定義在程式碼後面的函式在前面程式碼就可以使用,變數也是如此,但是變數提升的僅僅是變數的宣告語句,變數的賦值語句並沒有提升,所以提前使用的話只會得到undefined的變數。
此外,JS中規定迴圈和條件判斷沒有語句塊,所以在迴圈和條件判斷中宣告的變數在此之外還可以繼續使用,相當於變數宣告在外部。
以一段程式碼為例:
console.log(addNum());//這裡可以得出,function的作用域是這段程式碼的範圍
console.log(str);//這裡可以看出,str的宣告也被提升了,但是賦值並沒有被提升,所以結果是undefined
var num;
function addNum(){
num=0;
for(var i=5;i>0;i--){
num+=i;
}
console.log(i);//這裡可以看出,i在for和if之外還可以使用,for和if並沒有形成作用域,i的作用域是addNum內
return num;
}
var str="LI";
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 定時器
javascript是單執行緒的語言,所有函式都執行在一個執行緒中,只有前一個函式執行完了有一個函式才能佔用CUP執行,那麼在這種情況下看似跑在其他縣城上的定時器是如何工作的呢?
定時器也是跑在javascript的執行緒上,也因為此,javascript的定時器並不能準確定時。
如果當定時器時間到了,但是javascript當前卻有函式正在執行,則定時器的回撥函式會進行排隊,直到當前函式執行完之後才會執行定時器的回撥函式。
細緻一點說,定時器分為兩種setTimeout
和setInterval
,一個是定時一次,回撥函式執行一次就完了,一個是週期性定時,回撥函式會週期性執行。這兩種定時器在排隊的表現又有不同。
setTimeout的定時器表現如上所述,而setInterval定時器的表現卻有不同,想象一下,如果setInterval的回撥函式在第n次執行的時候,第n-1次的回撥函式還在排隊中沒有執行,第n次的回撥函式還會進入排隊嗎?答案是不會,同一個setInterval定時器,javascript不允許隊伍有多個同一個setInterval定時器的回撥函式進行排隊。
此外,在使用時,setTimeout和setInterval還有一個不同之處,考慮如下程式碼:
setTimeout(function test(){
//dosomething
setTimeout(test,10);
},10);
setInterval(function test(){
//dosomething
},10);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
上述兩種程式碼雖然都實現了週期性執行函式test的功能,但是setTimeout的執行間隔時間和setInterval並不同,setTimeout下一次test函式執行的時間是test內部所有程式碼執行完畢用時+10ms,而setInterval的執行間隔時間只有10ms,如果test函式的執行時間接近於或者大於10ms的話,setInterval的方法會使test連續執行,甚至引起test函式執行的排隊。