js的节流和防抖

1,节流

  节流就是对连续的函数触发,在设定的间隔时间段内,只让其执行一次。

  先来看看js高级程序设计3里面节流的代码

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

       当函数连续执行的时候,如果之前的定时器还没执行,就把它清除了,再从新设置一个新的定时器。

  我们可以对这个进行改进

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的第二个,设置定时器

     下一次执行(不超过wait时间内) :  remaining大于0,定时器为true,所以直接跳出

  

    understore里面的节流考虑了两个高级的配置:  是否在第一次触发的时候就执行函数 和  最后一次的定时器触发的执行函数。还提供了节流的取消函数。

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
}

  除了加了两个配置项和取消函数,别的基本都是一样的。

  需要注意的是,首次不执行和最后不执行这两个不能同时配置,只能配置一个。

 

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的话,那么触发第一次的时候就执行了要执行的函数,定时器里面不执行。

  

  

posted @ 2019-01-05 16:52  ken丶123  阅读(443)  评论(0编辑  收藏  举报