js的節流和防抖

1,節流

  節流就是對連續的函數觸發,在設定的間隔時間段內,只讓其執行一次。app

  先來看看js高級程序設計3裏面節流的代碼函數

function throttle (method, context, wait) {
    clearTimeout(method.tId)
     method.tId = setTimeout(function () {
         method.call(context)
     }, wait)
}

       當函數連續執行的時候,若是以前的定時器還沒執行,就把它清除了,再重新設置一個新的定時器。this

  咱們能夠對這個進行改進spa

function throttle (fn, wait) {
let timeout;
let prevTime = 0;
return function(...args) { //返回一個函數
let now = new Date();
let remaining = wait - (now - prevTime) // 下一次執行的時間,
if (remaining <=0 || remaining > wait) { // 若是下一次的時間小於等於0,馬上執行一次函數,並把時間戳改成當前的時間。
clearTimeout(timeout)
timeout = null
prevTime = now
fn.apply(this, args)
} else if (!timeout) { // 若是當前沒有定時器 那麼就新加一個定時器。
timeout = setTimeout(() => {
timeout = null;
prevTime = new Date();
fn.apply(this, args)
}, remaining)
}
}
}

  第一次執行: timeout爲undefined, prevTime爲0     remaining爲負數,走if的第一個,當即執行了函數並將下次時間改爲當前時間設計

  第二次執行: 下一次時間爲正,定時器仍是爲undefined,走if的第二個,設置定時器code

     下一次執行(不超過wait時間內) :  remaining大於0,定時器爲true,因此直接跳出blog

  

    understore裏面的節流考慮了兩個高級的配置:  是否在第一次觸發的時候就執行函數 和  最後一次的定時器觸發的執行函數。還提供了節流的取消函數。rem

function throttle(fn, wait, option = {}) {
        let timeout;
        let prevTime = 0
        let throttled = function(...args){
            let now = new Date();
            if (!prevTime && option.leading === false) prevTime = now;
            let remaining = wait - (now - prevTime);
            if (remaining <= 0 || remaining > wait) {
                if (timeout) {
                    clearTimeout(timeout)
                    timeout = null;
                }
                prevTime = now
                fn.apply(this, args)
            } else if (!timeout && option.trailing !== false) {
                timeout = setTimeout(() => {
                    prevTime = option.leading === false ? 0 : new Date;
                    fn.apply(this, args)
                })
            }
        }
        throttled.cancel = () => {
            clearTimeout(timeout);
            prevTime = 0;
            timeout = null;
        }
        return throttled
}

  除了加了兩個配置項和取消函數,別的基本都是同樣的。underscore

  須要注意的是,首次不執行和最後不執行這兩個不能同時配置,只能配置一個。it

 

2,防抖

  其實我感受防抖和節流差異不大,主要的差異在於: 在wait的時間內,反覆觸發函數的話,節流不會理會這些,而防抖的話,只要你觸發了,他就會清除以前的定時器,重新設置一個定時器。

  好比說坐電梯,若是是節流的話,電梯等待時間爲5S,從第一我的進電梯開始算,到5S後他就會關門運行。

           若是是防抖的話,電梯等待時間爲5S,在這5S以內,若是有人進電梯,他就會從新計時,只有在5S中沒有人進電梯了,電梯才關門運行。

function debounce (fn, wait) {
let timeout;
return function(...args) {
if (timeout) clearTimeout(timeout);
timeout = setTimeout(() => {
fn.apply(this, args)
}, wait)
}
}

  返回一個函數, 先清除以前的定時器,而後再新加定時器。

 

  underscore裏面的防抖添加了一個高級配置,是否當即執行一次函數。

function debounce(fn, wait, immediate) {
       let timeout;
       return function(...args) {
           let callNow = immediate && !timeout;
           if (timeout) clearTimeout(timeout);
           timeout = setTimeout(() => {
               timeout = null;
               if (!immediate) fn.apply(this, args)
           }, wait)
           if (callNow) fn.apply(this, args)
       }
}

  這裏添加了immediate這個配置項,若是爲true的話,那麼觸發第一次的時候就執行了要執行的函數,定時器裏面不執行。

相關文章
相關標籤/搜索