函数防抖和节流

防抖

对于触发非常频繁又没有必要每次都执行的事件,希望合并到一次去执行;

实现思路:

事件触发后,在规定的时间范围内如果事件重复触发,那么忽略之前触发的事件,并且重新开始计时,直到某一次事件触发后大于规定时间,我们才执行需要执行的代码段(函数);

看起来就像是只执行了用户快速操作的最后一次事件;

  • 代码实现:
var debounce = function(fn, delayTime) {
 var timeId;
 return function() {    
    var context = this, args = arguments;
       timeId && clearTimeout(timeout);
       timeId = setTimeout(function{
          fn.apply(context, args);
    }, delayTime)
  }
}
  • 简单分析:

利用闭包保存一个setTimeout的id,如果在delayTime内闭包中的函数再次执行,会立刻clear掉上一次的延时回调,生成一个新的延时回调;如果超过delayTime没有再次执行闭包中的函数,那延时回调就会被执行,这样才算是真正执行了需要执行的事件。

  • 应用场景:
  1. 给按钮加函数防抖防止表单多次提交。
  2. 对于输入框连续输入进行AJAX验证时,用函数防抖能有效减少请求次数。
  3. 判断scroll是否滑到底部,滚动事件+函数防抖

节流

对于触发非常频繁的事件,在规定时间间隔后才能执行,在规定时间间隔内触发的事件会被忽略,但是不会重新开始计时

  • 实现思路:

规定一个时间,一次触发后,在规定时间内触发的事件都忽略,超过规定时间后可以重新执行触发的事件;

  • 代码实现:(两种)
  1. 时间戳
var throttle = (fn, delayTime) => {
    var _start = Date.now();
    return function() {
        var _now = Date.now(), context = this, args = arguments;
        if(_now - _start >= delayTime) {
              fn.apply(context, args);
               _start = Date.now();
        }
      }
}
  • 简单分析:

先设定一个初始时间,然后每次执行闭包内的函数都与当前时间做比较,如果小于delayTime,什么也不做,忽略该次事件,如果大于delayTime,执行回调函数fn,重置初始时间;

  1. 定时器
var throttle = function(fn, delayTime) {
      var flag;
      return function() {
        var context = this, args = arguments;
        if(!flag) {
            fn.apply(context, args);
              flag = setTimeout(function() {    
                  flag = false;
            }, delayTime);
          }
      }
}
  • 简单分析:

通过设定一个标志位,通过标志位判断是否可以执行回调函数,在延时函数中执行回调的同时将标志位置为可再次执行,这样就保证了在规定时间之后能再次执行需要的回调函数;

  • 应用场景:
  1. 游戏中的刷新率
  2. DOM元素拖拽
  3. Canvas画笔功能

防抖和节流区别

  • 防抖是把之前频繁的事件触发都放到某一次停顿时触发,可以理解为执行最后一次(并不准确);节流则是执行完一次以后等待一段时间之后才能再次执行,可以理解为第一次;这意味着防抖执行的是最新的,而节流在等待中如果事件有更新是不会执行的,会被忽略,这两者应用场景不同;
  • 防抖适合多次事件一次响应的情况;
  • 节流适合大量事件按时间做平均分配触发。

参考:

十分钟学会防抖和节流

轻松理解JS函数节流和函数防抖


木木俞
192 声望5 粉丝

佛系前端