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講啦!