函數節流

講真 哪一個是節流throttle,哪一個是去抖debounce,無所謂啦。。。javascript

硬要區分的話,我以爲是這種:css

http://blog.peterwf.com/2015/11/17/debounce-throttle/前端

參考:https://css-tricks.com/the-difference-between-throttling-and-debouncing/java

 

或者就不要區分了,就都是節流。這個講得最好:sublime-text

http://www.alloyteam.com/2012/11/javascript-throttle/#prettyPhoto瀏覽器

 function throttle(fn,delay){
        var timer = null;
        console.log(this);//window
        return function (){//使用閉包,保證了全局的timer
            var context = this, args = arguments;
//            console.log(this);//btn
            clearTimeout(timer);
            timer = setTimeout(function (){
                fn.apply(context,args);//context保證了fn裏的this的正確性:btn
            },delay);
        };
    };
    function fn(){
        console.log(this);
        console.log("執行");
    }
    $("#btn").on("click",throttle(fn, 1000));
    //click以前就執行了throttle。執行結果給了click
//    $("#btn").on("click",fn);

什麼是函數節流?

介紹前,先說下背景。在前端開發中,有時會爲頁面綁定resize事件,或者爲一個頁面元素綁定拖拽事件(其核心就是綁定mousemove),這種事件有一個特色,就是用戶沒必要特意搗亂,他在一個正常的操做中,都有可能在一個短的時間內觸發很是屢次事件綁定程序。而你們知道,DOM操做時很消耗性能的,這個時候,若是你爲這些事件綁定一些操做DOM節點的操做的話,那就會引起大量的計算,在用戶看來,頁面可能就一時間沒有響應,這個頁面一會兒變卡了變慢了。甚至在IE下,若是你綁定的resize事件進行較多DOM操做,其高頻率可能直接就使得瀏覽器崩潰。閉包

怎麼解決?函數節流就是一種辦法。話說第一次接觸函數節流(throttle),仍是在看impress源代碼的時候,impress在播放的時候,若是窗口大小發生改變(resize),它會對總體進行縮放(scale),使得每一幀都完整顯示在屏幕上:app

impress在resize的時候自動適應

稍微留心,你會發現,當你改變窗體大小的時候,無論你怎麼拉,怎麼拽,都沒有馬上生效,而是在你改變完大小後的一下子,它的內容才進行縮放適應。看了源代碼,它用的就是函數節流的方法。ide

函數節流,簡單地講,就是讓一個函數沒法在很短的時間間隔內連續調用,只有當上一次函數執行後過了你規定的時間間隔,才能進行下一次該函數的調用。以impress上面的例子講,就是讓縮放內容的操做在你不斷改變窗口大小的時候不會執行,只有你停下來一下子,纔會開始執行。函數

 

函數節流的原理

函數節流的原理挺簡單的,估計你們都想到了,那就是定時器。當我觸發一個時間時,先setTimout讓這個事件延遲一會再執行,若是在這個時間間隔內又觸發了事件,那咱們就clear掉原來的定時器,再setTimeout一個新的定時器延遲一會執行,就這樣。

代碼實現

明白了原理,那就能夠在代碼裏用上了,但每次都要手動去新建清除定時器畢竟麻煩,因而須要封裝。在《JavaScript高級程序設計》一書有介紹函數節流,裏面封裝了這樣一個函數節流函數:

它把定時器ID存爲函數的一個屬性(= =我的的世界觀不喜歡這種寫法)。而調用的時候就直接寫

這樣兩次函數調用之間至少間隔100ms。

而impress用的是另外一個封裝函數:

它使用閉包的方法造成一個私有的做用域來存放定時器變量timer。而調用方法爲

兩種方法各有優劣,前一個封裝函數的優點在把上下文變量當作函數參數,直接能夠定製執行函數的this變量;後一個函數優點在於把延遲時間當作變量(固然,前一個函數很容易作這個拓展),並且我的以爲使用閉包代碼結構會更優,且易於拓展定製其餘私有變量,缺點就是雖然使用apply把調用throttle時的this上下文傳給執行函數,但畢竟不夠靈活。

接下來是?

接下來就討論怎麼更好地封裝?這多沒意思啊,接下來討論下怎樣拓展深化函數節流。

真是棒!

http://www.alloyteam.com/2012/11/javascript-throttle/#prettyPhoto

相關文章
相關標籤/搜索