javascript函數的throttle和debounce

上週寫了window resize和scroll事件的基本優化,結果微博上交流的人還挺多,你們都提到了一個技術名詞:「throttle」。 javascript

throttle

咱們這裏說的throttle就是函數節流的意思。再說的通俗一點就是函數調用的頻度控制器,是連續執行時間間隔控制。主要應用的場景好比: css

  • 鼠標移動,mousemove 事件
  • DOM 元素動態定位,window對象的resize和scroll 事件

有人形象的把上面說的事件形象的比喻成機關槍的掃射,throttle就是機關槍的扳機,你不放扳機,它就一直掃射。咱們開發時用的上面這些事件也是同樣,你不鬆開鼠標,它的事件就一直觸發。回到window resize和scroll事件的基本優化提到的優化: 前端

var resizeTimer = null;
$(window).on('resize', function () {
        if (resizeTimer) {
            clearTimeout(resizeTimer)
        }
        resizeTimer = setTimeout(function(){
            console.log("window resize");
        }, 400);
    }
);

setTimeout和clearTimeout其實就是一個簡單的 throttle,不少好的控制了resize事件的調用頻度。 java

debounce

debounce和throttle很像,debounce是空閒時間必須大於或等於 必定值的時候,纔會執行調用方法。debounce是空閒時間的間隔控制。好比咱們作autocomplete,這時須要咱們很好的控制輸入文字時調用方法時間間隔。通常時第一個輸入的字符立刻開始調用,根據必定的時間間隔重複調用執行的方法。對於變態的輸入,好比按住某一個建不放的時候特別有用。 jquery

debounce主要應用的場景好比: app

  • 文本輸入keydown 事件,keyup 事件,例如作autocomplete

這類網上的方法有不少,好比Underscore.js就對throttle和debounce進行封裝。jQuery也有一個throttle和debounce的插件:jQuery throttle / debounce,全部的原理時同樣的,實現的也是一樣的功能。再奉上一個本身一直再用的throttle和debounce控制函數: 函數

/*
 * 頻率控制 返回函數連續調用時,fn 執行頻率限定爲每多少時間執行一次
 * @param fn {function}  須要調用的函數
 * @param delay  {number}    延遲時間,單位毫秒
 * @param immediate  {bool} 給 immediate參數傳遞false 綁定的函數先執行,而不是delay後後執行。
 * @return {function}	實際調用函數
 */
var throttle = function (fn,delay, immediate, debounce) {
    var curr = +new Date(),//當前事件
        last_call = 0,
        last_exec = 0,
        timer = null,
        diff, //時間差
        context,//上下文
        args,
        exec = function () {
            last_exec = curr;
            fn.apply(context, args);
        };
    return function () {
        curr= +new Date();
        context = this,
        args = arguments,
        diff = curr - (debounce ? last_call : last_exec) - delay;
        clearTimeout(timer);

        if (debounce) {
            if (immediate) {
                timer = setTimeout(exec, delay);
            } else if (diff >= 0) {
                exec();
            }
        } else {
            if (diff >= 0) {
                exec();
            } else if (immediate) {
                timer = setTimeout(exec, -diff);
            }
        }

        last_call = curr;
    }
};

/*
 * 空閒控制 返回函數連續調用時,空閒時間必須大於或等於 delay,fn 纔會執行
 * @param fn {function}  要調用的函數
 * @param delay   {number}    空閒時間
 * @param immediate  {bool} 給 immediate參數傳遞false 綁定的函數先執行,而不是delay後後執行。
 * @return {function}	實際調用函數
 */
var debounce = function (fn, delay, immediate) {
    return throttle(fn, delay, immediate, true);
};

demo:http://www.css88.com/demo/throttle_debounce/ 優化

更多閱讀: this

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

http://remysharp.com/2010/07/21/throttling-function-calls/

聲明: 本文采用 BY-NC-SA 協議進行受權 | WEB前端開發
轉載請註明轉自《javascript函數的throttle和debounce

相關文章
相關標籤/搜索