我们在开发的过程中,经常会有这样一种情况,函数被频繁的调用,如果这个函数执行了某些dom操作的话,那么浏览器将会非常耗费性能,从而影响用户体验

通过设置定时器保证一段时间内事件回调函数只能执行一次的做法在javascript业界有一个专业的术语称谓——防抖!

 它的原理其实很简单:1 用闭包实现一个timer变量,用来保存上一次调用函数的定时器id;2 我们不是直接调用函数,而是中间需要一个间隔,如果两次调用之间的时间差小于我们传递的值,那么清空上一次的调用值;3 我们每一次调用的时候都清除一下上一次的调用定时器id,这样就保证了,如果间隔时间小于我们设置的值,那么上一次函数一定不会调用,从而达到了降低调用频率的效果。

// 限制调用频率
        function debounce(fn,time){
            //设置定时器
            let timer;
            return function(...args){
                //清空上一次的定时器
                clearTimeout(timer);
                //获取执行环境的上下文
                let context = this;
                let _arguments = args;
                timer = setTimeout(()=>{
                    fn.apply(context,_arguments);
                },time);
            };
        };

函数节流(throttle):当持续触发事件时,保证一定时间段内只调用一次事件处理函数。

主要有两种方式实现:

  • 法一:时间差,原理无非就是两次调用之间的时间差小于设置时,那么不调用,反之调用。代码如下:
function ttrottle(fn,time){
  //上一次调用时间
  let lastInvokeTime = new Date().getTime();
  //当前调用时间
  let currentInvokeTime;
  return function(...args){
    currentInvokeTime = new Date().getTime();
    if(currentInvokeTime - lastInvokeTime <= time)return;
    let context = this;
    let _arguments = args;
    lastInvokeTime = currentInvokeTime;
    fn.apply(context,_arguments);
  };
};

  • 法二:定时器实现,原理就是设置时间间隔,如果达不到时间间隔,就清除上一次调用回调定时器id。代码如下: 
  • function ttrottle(fn,time){
        let isNeedInvoke = true;
        return function(...args){
            if(!isNeedInvoke)return;
            let context = this;
            let _arguments = args;
            isNeedInvoke = false;
            setTimeout(()=>{
                fn.apply(context,_arguments);
                isNeedInvoke = true;
            },time);
        };
    };