1. 程式人生 > >js中定時器setTimeout和setInterval兩種定時器

js中定時器setTimeout和setInterval兩種定時器

專案中,經常會用到定時器來實現資料實時更新、時間等,簡單總結一下:

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主執行緒程式碼後,再執行定時器延遲執行的程式碼。


變數作用域和定時器

  1. 變數提升 
    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
  1. 定時器 
    javascript是單執行緒的語言,所有函式都執行在一個執行緒中,只有前一個函式執行完了有一個函式才能佔用CUP執行,那麼在這種情況下看似跑在其他縣城上的定時器是如何工作的呢? 
    定時器也是跑在javascript的執行緒上,也因為此,javascript的定時器並不能準確定時。 
    如果當定時器時間到了,但是javascript當前卻有函式正在執行,則定時器的回撥函式會進行排隊,直到當前函式執行完之後才會執行定時器的回撥函式。 
    細緻一點說,定時器分為兩種setTimeoutsetInterval,一個是定時一次,回撥函式執行一次就完了,一個是週期性定時,回撥函式會週期性執行。這兩種定時器在排隊的表現又有不同。 
    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函式執行的排隊。