BOM之定時器

JavaScript中的時間是經過定時器控制的,他們分別是window.setInterval和window.setTimeout,咱們固然能夠省略window,直接使用方法名稱調用。css

 

一       setTimeoutjson

  在等待指定的毫秒數後執行函數,語法以下:瀏覽器

  setTimeout(code/function, milliseconds, param1, param2, ...)函數

  方法接受2個或多個參數,第一個是一段JS代碼或一個函數引用,第二個是須要等待的時間(以毫秒計),若是第一個參數是函數引用,而且須要傳遞參數,能夠在後面依次傳入。方法返回一個惟一id,表明該定時器,使用clearTimeout(id)能夠清除定時器。測試

1 setTimeout(functon(){
2         console.log(new Date());
3     },3000);
4 console.log(new Date());
5 //當即顯示一次當前時間,3秒後又將顯示一次

  經測試發現:若是第一個參數是一段JS代碼而非函數引用,該代碼將當即被執行,而不會延時等待。動畫

 

二     setIntervalspa

  等同於 setTimeout(),但持續重複執行該函數。語法以下:線程

  setInterval(code/function, milliseconds, param1, param2, ...)code

  使用方法和setTimeout()相同。對象

1 function timer(){
2     var d = new Date();
3     document.body.innerText = d;
4 }
5 setInterval(timer,1000);

  上面是一個簡單的定時器示例。

  另外,setInterval方法有一個嚴重的缺陷,那就是不能確保執行時間的準確性。

在執行setInterval()時,假如咱們設置每1s執行一次函數,但函數執行一次須要花費2s。瀏覽器會每隔1s就向一個事件隊列中添加一個事件(即執行一次函數),當第一次執行完畢(3s以後了),這時隊列中已經有2個事件正在排隊了,因而瀏覽器當即執行第二個事件(等待隊列中的第一個)。這樣明顯和咱們本意每1s執行一次函數不符。因此在setInterval中,與其說第二個參數是延時時間,不如說是每一個事件執行的最大間隔時間更爲準確。由於當事件執行時間大於設置的間隔時間時,兩個任務執行之間是沒有間隔時間的。

  有些書上表示,到了設置的時間點,若是上一次的函數還沒執行完,那麼本次事件將不會被添加到事件隊列中去,此次事件將被跳過,直到將來設置的某一時間點,前面的任務已經完成,才向隊列中添加下一個事件。但瀏覽器其實是按照第一種方式管理事件隊列的,即到了時間無論前面的是否執行完畢,都插入一個進去,而後依次等待執行。(我用的Chrome  76.0.3869.100測試)

  setInterval主要應用在繪製動畫效果上,鑑於它對時間的不許確性,要想得到完美的動畫效果請使用CSS3的Animation實現。另外,若是確實須要使用,請務必把握好間隔時間的設置。下面是使用setInterval封裝的一個運動函數:

 1 var timer;
 2 function startMove(obj,json,Fn){
 3     var key;
 4     clearInterval(timer);
 5     timer = setInterval(function(){
 6         for(var prop in json){//json是一個包含須要改變的屬性和目標值的對象。  7             var bridge;
 8             if(prop == 'opacity'){
 9                 bridge = getStyle(obj,prop)*100;//爲了便於計算,先放大100倍 10             }else{
11                 bridge = parseInt(getStyle(obj,prop));
12             }
13             var speed = (json[prop] - bridge)/6;
14             speed = speed > 0?Math.ceil(speed):Math.floor(speed);//這裏爲了得到更好的動畫效果,動態設置了運動速度。你固然能夠給一個常數做爲運動速度 15             if(prop == 'opacity'){
16                 obj.style[prop] = (bridge + speed) / 100;
17             }else{
18                 obj.style[prop]= bridge + speed + 'px';
19             }
20             if(bridge != json[prop]){
21                 key = false;
22             }else{
23                 key = true;
24             }
25             if(key){
26                 clearInterval(timer);
27                 if(Fn)Fn();//當目標運動完成,執行回調函數 28             }
29         }
30     },30);
31 }
32     
33 function getStyle(obj,prop){//獲取css樣式值
34     if(obj.currentStyle){//IE 35         return obj.currentStyle(prop);
36     }else{//其餘 37         return getComputedStyle(obj,false)[prop];
38     }
39 }

 

  網上不少文章亦或是不少出版書籍都把這兩個方法和DOM放在一塊兒或者單獨講解,我想他們這麼作的緣由大概是這兩個方法在JavaScript中主要應用在實現DOM元素的動畫效果上。那麼我爲何要把他們放在BOM裏面講呢?

  咱們知道,JS的執行是單線程的,當代碼運行到這兩個方法時,理論上應該等待它綁定的代碼執行完再日後執行其餘代碼,實際上他們並不會阻塞後面的代碼,這又是爲何呢?原來每當遇到延時程序時,瀏覽器都會爲它單獨開啓一個線程,換言之,他們的時間是由瀏覽器操縱的,而不是JavaScript。另外一個明顯的理由是這兩個方法原本就是綁定在window對象上的,是由瀏覽器實現的,因此我把它放在BOM講啦!

相關文章
相關標籤/搜索