JavaScript之節流與防抖

weixin_34402408發表於2018-07-31

背景

我們在開發的過程中會經常使用如scroll、resize、touchmove等事件,如果正常繫結事件處理函式的話,有可能在很短的時間內多次連續觸發事件,十分影響效能。
因此針對這類事件要進行節流或者防抖處理

節流

節流的意思是,在規定的時間內只會觸發一次函式,如我們設定函式500ms觸發一次,之後你無論你觸發了多少次函式,在這個時間內也只會有一次執行效果

先來看一個例子

https://codepen.io/wclimb/pen/gKWLpO/

我們看到使用了節流的在1000ms內只觸發了一次,而沒有使用節流的則頻繁觸發了呼叫的函式

接下來看看程式碼實現
v1 第一次不觸發,不傳參實現

function throttle(fn,interval){
    var timer;
    return function(){
        if(timer){
            return
        }
        timer = setTimeout(() => {
            clearTimeout(timer)
            timer = null
            fn()
        }, interval || 1000);
    }   
}

效果是實現了,但是我在嘗試在執行函式裡console.log(this),結果發現this指向的是window,而且還發現我們不能傳遞引數,下面就來改進一下

v2 第一次觸發函式,接收引數

function throttle(fn,interval){
    var timer,
        isFirst = true;
    return function(){
        var args = arguments,
            that = this;
        if(isFirst){
            fn.apply(that,args)
            return isFirst = false
        }
        if(timer){
            return
        }
        timer = setTimeout(() => {
            clearTimeout(timer)
            timer = null
            fn.apply(that,args)
        }, interval || 1000);
    }   
}

防抖

防抖的意思是無論你觸發多少次函式,只會觸發最後一次函式。最常用的就是在表單提交的時候,使用者可能會一段時間內點選很多次,這個時候可以增加防抖處理,我們只需要最後一次觸發的事件

先來看一個例子

https://codepen.io/wclimb/pen/pKPeyv/

我們看到使用了防抖的方框,無論你在裡面觸發了多少次函式,都只會觸發最後的那一次函式,而沒有使用防抖的則頻繁觸發了呼叫的函式

v1 第一次不觸發函式

function debounce(fn,interval){
    var timer;
    return function(){
        var args = arguments,
            that = this;
        if(timer){
            clearTimeout(timer)
            timer = null
        }
        timer = setTimeout(() => {
            fn.apply(null,args)
        }, interval || 1000);
    }
}

上面這段程式碼仍然可以正常執行,但是我們並沒有指定他的this

v2 第一次就觸發函式

function debounce(fn,interval){
    var timer,
        isFirst  = true,
            can = false;
    return function(){
        var args = arguments,
            that = this;
        if(timer){
            clearTimeout(timer)
            timer = null
        }
        if(isFirst){
            fn.apply(that,args)
            isFirst = false
            setTimeout(() => {
                can = true
            }, interval || 1000);
        }else if(can){
            timer = setTimeout(() => {
                fn.apply(null,args)
            }, interval || 1000);
        }
    }
}

如有雷同,純屬抄我(開玩笑)

如有錯誤,還望指正,僅供參考

GitHub:wclimb

相關文章