JavaScript 函數節流 throttle 和防抖 debounce

今天和別人聊到JavaScript函數的節流和防抖,發現本身對這兩個的區別非常模糊,遂小小實踐一下,在此記錄,但願對須要的人有所幫助。app

節流 - 頻繁操做,間隔必定時間去作一件事

舉例說明:假定時間間隔爲 500ms,頻繁不停的操做 2s,且每兩次執行時間小於等於時間間隔 500ms,那麼就會執行 4 次,也就是每隔 時間間隔 500ms 執行一次。函數

防抖 - 頻繁操做,必定時間間隔內只執行最後一次操做

舉例說明:假定時間間隔是 500ms,頻繁不停的操做 5s,且每兩次執行時間小於等於時間間隔 500ms,那麼最後只執行了 1 次,也就是每一次執行時都結束了上一次的執行。this

代碼示例

//節流方法 1
    function throttle1(method, duration){
        var prevTime = new Date();
        return function () {
            var context = this,
                currentTime = new Date(),
                resTime = currentTime - prevTime;
            //打印出本次調用方法和上次執行方法的時間差
            console.log("時間差"+resTime);
            //當本次調用距離上次執行方法的時間差大於等於要求時間間隔時,執行一次方法
            if(resTime >= duration){
                method.apply(context);
                //記錄執行方法的時間
                prevTime = currentTime;
            }
        }
    }
    //節流方法 2
    function throttle2(method, duration){
        //當前時間間隔內是否有方法在執行(或者說方法的調用是否在進行)
        var runningFlag = false;
        return function (e) {
            // 判斷當前是否有方法在執行,有,則什麼都不作
            if (runningFlag) {
                return false;
            }
            //開始執行
            runningFlag = true;
            setTimeout(function(){
                method(e);
                //執行完畢,聲明當前沒有正在執行的方法,方便下一個時間間隔內的調用
                runningFlag = false;
            }, duration)
        }
    }
    //防抖
    function debounce(method, duration){
        var timer = null;
        return function(){
            var context = this,
                args = arguments;
            //在本次調用以前的一個間隔時間內,有方法在執行,則終止該方法的執行
            if(timer){
                clearTimeout(timer);
            }
            //開始執行本次調用
            timer = setTimeout(function(){
                method.apply(context, args);
            },duration);
        }
    }
    //模擬三個執行方法
    function jieliu1(){
        console.log("節流 1");
    }
    function jieliu2(){
        console.log("節流 2");
    }
    function fangdou(){
        console.log("防抖");
    }
    //持續執行時間
    var totalTime = 2000;

    var jieliuFn1 = throttle1(jieliu1,500);
    var jieliuFn2 = throttle2(jieliu2,500);
    var fangdouFn = debounce(fangdou,500);

    (function(duration){
        setInterval(function(){
            if( totalTime > 0 ){
                jieliuFn1();
                jieliuFn2();
                fangdouFn();
                totalTime -= duration;
            }
        },duration);
    })(100);

運行結果

時間差 100
時間差 201
時間差 303
時間差 401
時間差 504
節流 1
時間差 98
節流 2
時間差 199
時間差 300
時間差 396
時間差 496
時間差 597
節流 1
時間差 100
節流 2
時間差 203
時間差 299
時間差 402
時間差 500
節流 1
時間差 103
時間差 204
節流 2
時間差 303
時間差 400
節流 2
防抖

結論

由以上運行結果能夠看出,節流1 出現了 3 次,節流2 出現了 4 次,防抖出現了 1 次。防抖實現順利,可是兩個節流方法的執行結果存在差別。
觀察時間差能夠看出,每次節流1 執行時,時間差並不會都是 500 整,也就是說,一共調用 2 秒時,節流1 並不能作到每隔 500 毫秒執行一次而共執行 4 次,第四次執行每每由於前面的 3 次執行的時間偏差,而致使到達時間 2 秒時,最後一次的時間差沒法達到 時間間隔 500ms 以上,以致於只能執行 3 次。code

結論:當在一個大範圍的時間內,好比兩小時內,每幾分鐘執行一次,超過2小時則再也不實行,推薦使用第一種節流方式,;若是僅僅要求間隔必定時間執行一次,推薦使用第二種節流方法;防止頻繁操做,好比表單屢次提交,推薦使用防抖。ip

若有問題,歡迎指正,謝謝!

相關文章
相關標籤/搜索