你所不瞭解的setTimeout

 

你所不瞭解的setTimeout

關於setInterval()和setTimeout()返回值

setInterval(),setTimeout() 會返回一個值,通常認爲是ID,將這個ID值傳遞給clearInterval(),clearTimeout() 能夠取消執行,例如:javascript

1
2
3
4
5
6
7
8
var  intervalTimer = setInterval( function () {
     console.log(1)
},
3000);
console.log(intervalTimer);  //通常是一個數字,Number
button.onclick =  function () {
     clearInterval(intervalTimer);
};

關於setInterval()和setTimeout()中回調函數中的this

setInterval(),setTimeout() 方法是瀏覽器 window 對象提供,因此第一個參數函數中的this指向window對象,這跟變量的做用域有關:html

1
2
3
4
5
6
7
8
9
10
11
var  a = 1;
var  obj = {
     a: 2,
     b:  function () {
         setTimeout( function () {
             console.log( this .a);  //這裏返回的是:1;
         },
         2000);
     }
};
obj.b();

固然你能夠經過使用bind()方法來改變這個狀況:html5

1
2
3
4
5
6
7
8
9
10
var  a = 1;
var  obj = {
     a: 2,
     b:  function () {
         setTimeout( function () {
             console.log( this .a);  //這裏返回的是:2;
         }.bind( this ), 2000);  //注意這行
     }
};
obj.b();

關於bind()方法,你能夠看這裏:http://helloweb.wang/qianduankaifa/Js%20JQuery/2015-12-06/403.htmljava

關於setInterval()和setTimeout()的參數

你們都知道setInterval()和setTimeout()能夠接收兩個參數,第一個參數是須要回調的函數,必須傳入的參數,第二個參數是時間間隔,毫秒數,能夠省略,這個能夠看文章的下面,不傳第二個參數,瀏覽器自動配置時間,在IE,FireFox中,第一次配可能給個很大的數字,100ms上下,日後會縮小到最小時間間隔,Safari,chrome,opera則多爲10ms上下。web

可是我要說的固然不是這個,我要說的是setInterval()和setTimeout()能夠接收更多的參數,那麼這些參數是幹什麼用的呢?從第三個參數開始,依次用來表示第一個參數(回調函數)傳入的參數,例如:chrome

1
2
3
setTimeout( function (a,b){
     console.log(1+a+b); //這裏打印的是:8
},1000,3,4);

固然一些古老的瀏覽器是不支持的。後端

關於clearInterval()和clearTimeout()

clearInterval()和clearTimeout()實際上是通用的,就是說你能夠用 clearInterval() 取消 setTimeout() 執行,clearTimeout()一樣能夠取消 setInterval() 執行。瀏覽器

1
2
3
4
5
6
7
8
var  intervalTimer = setInterval( function () {
     console.log(1)
},
3000);
console.log(intervalTimer);
button.onclick =  function () {
     clearTimeout(intervalTimer);  //注意這裏,不是clearInterval哦
};

教科書裏面的setTimeout

定義很簡單多線程

setTimeout() 方法用於在指定的毫秒數後調用函數或計算表達式。框架

普遍應用場景:定時器,輪播圖,動畫效果,自動滾動等等

上面一些應該是setTimeout在你們心中的樣子,由於咱們日常使用也不是不少。

可是setTimeout真的有那麼簡單嗎?

測試題

一個題目,若是你在一段代碼中發現下面內容

1
2
3
4
var  startTime =  new  Date();
setTimeout( function  () {    
     console.log( new  Date() - startTime);
}, 100)

請問最後打印的是多少?

我以爲正確答案是,取決於後面同步執行的js須要佔用多少時間。

MAX(同步執行的時間, 100)。

再加一個題目,只有下面代碼

1
2
3
4
setTimeout( function  () {
     func1();
}, 0)
func2();

func1和func2誰會先執行?

這個答案應該比較簡單,func2先執行,func1後面執行。

再來一題

1
2
3
setTimeout( function  () {    
     func1()
}, 0)

1
2
3
setTimeout( function  () {    
     func1()
})

有什麼差異?

0秒延遲,此回調將會放到一個能當即執行的時段進行觸發。javascript代碼大致上是自頂向下的,但中間穿插着有關DOM渲染,事件迴應等異步代碼,他們將組成一個隊列,零秒延遲將會實現插隊操做。

不寫第二個參數,瀏覽器自動配置時間,在IE,FireFox中,第一次配可能給個很大的數字,100ms上下,日後會縮小到最小時間間隔,Safari,chrome,opera則多爲10ms上下。

上面答案來自《javascript框架設計》

好了,看了上面幾個題目是否是感受setTimeout不是想象中那樣了。

setTimeout和單線程

下面是我本身的一些理解:

首先須要注意javascript是單線程的,特色就是容易出現阻塞。若是一段程序處理時間很長,很容易致使整個頁面hold住。什麼交互都處理不了怎麼辦?

簡化複雜度?複雜邏輯後端處理?html5的多線程?

上面都是ok的作法,可是setTimeout也是處理這種問題的一把好手。

setTimeout一個很關鍵的用法就是分片,若是一段程序過大,咱們能夠拆分紅若干細小的塊。

例如上面的狀況,咱們將那一段複雜的邏輯拆分處理,分片塞入隊列。這樣即便在複雜程序沒有處理完時,咱們操做頁面,也是能獲得即便響應的。其實就是將交互插入到了複雜程序中執行。

換一種思路,上面就是利用setTimeout實現一種僞多線程的概念。

有個函數庫Concurrent.Thread.js 就是實現js的多線程的。

一個簡單使用的例子,引入Concurrent.Thread.js後

1
2
3
4
5
6
7
8
Concurrent.Thread.create( function () {
     for  ( var  i = 0; i < 1000000; i++) {
         console.log(i);
     };
});
$( '#test' ).click( function () {
     alert(1);
});

雖然有個巨大的循環,可是這時不妨礙你去觸發alert();

是否是很厲害~

還有一種場景,當咱們須要渲染一個很複雜的DOM時,例如table組件,複雜的構圖等等,假如整個過程須要3s,咱們是等待徹底處理完成在呈現,仍是使用一個setTimeout分片,將內容一片一片的斷續呈現。

其實setTimeout給了咱們不少優化交互的空間。

相關文章
相關標籤/搜索