js 函數節流 jQuery throttle/debounce

在《JavaScript高級程序設計》一書有介紹函數節流,裏面封裝了這樣一個函數節流函數:閉包

function throttle(method, context) {
     clearTimeout(methor.tId);
     method.tId = setTimeout(function(){
         method.call(context);
     }, 100);
 }

它把定時器ID存爲函數的一個屬性。而調用的時候就直接寫app

window.onresize = function(){
    throttle(myFunc);
}

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

var throttle = function(fn, delay){
    var timer = null;
    return function(){
        var context = this, args = arguments;
        clearTimeout(timer);
        timer = setTimeout(function(){
            fn.apply(context, args);
        }, delay);
    };
 };

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

window.onresize = throttle(myFunc, 100);

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

上面介紹的函數節流,它這個頻率就不是50ms之類的,它就是無窮大,只要你能不間斷resize,刷個幾年它也一次都不執行處理函數。咱們能夠對上面的節流函數作拓展:code

var throttleV2 = function(fn, delay, mustRunDelay){
    var timer = null;
    var t_start;
    return function(){
        var context = this, args = arguments, t_curr = +new Date();
        clearTimeout(timer);
        if(!t_start){
            t_start = t_curr;
        }
        if(t_curr - t_start >= mustRunDelay){
            fn.apply(context, args);
            t_start = t_curr;
        }
        else {
            timer = setTimeout(function(){
                fn.apply(context, args);
            }, delay);
        }
    };
 };

在這個拓展後的節流函數升級版,咱們能夠設置第三個參數,即必然觸發執行的時間間隔。若是用下面的方法調用ip

window.onresize = throttleV2(myFunc, 50, 100);

則意味着,50ms的間隔內連續觸發的調用,後一個調用會把前一個調用的等待處理掉,但每隔100ms至少執行一次。原理也很簡單,打時間tag,一開始記錄第一次調用的時間戳,而後每次調用函數都去拿最新的時間跟記錄時間比,超出給定的時間就執行一次,更新記錄時間。作用域

相關文章
相關標籤/搜索