函数节流与函数防抖

以下场景往往由于事件频繁被触发,因而频繁执行DOM操作、资源加载等重行为,导致UI停顿甚至浏览器崩溃。

  1. window对象的resize debounce

  2. scroll事件 throttle

  3. 拖拽时的mousemove事件 debounce

  4. 射击游戏中的mousedown、keydown事件 debounce

  5. 文字输入、自动完成的keyup事件 debounce

实际上对于window的resize事件,实际需求大多为停止改变大小n毫秒后执行后续处理;而其他事件大多的需求是以一定的频率执行后续处理。针对这两种需求就出现了debounce和throttle两种解决办法。

debounce

当频繁改变窗口大小时,你会发现 fn压根没有被调用过!直到你停下来后,fn才会被调用一次。

const debounce = (fn, ms = 0) => {
  let timeoutId;
  return function(...args) {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => fn.apply(this, args), ms);
  };
};
// 使用
window.addEventListener(
  'resize',
  debounce(() => {
    console.log(window.innerWidth);
  }, 1000)
);

throttle

当频繁改变窗口大小时,throttle 会保证在每 wait时间调用 fn一次。

(我们的直观感觉是使用 throttle 方法相比于 debounce 方法事件触发的频率更高一些)

const throttle = (fn, wait) => {
  let inThrottle, lastFn, lastTime;
  return function() {
    const context = this,
      args = arguments;
    if (!inThrottle) {
      fn.apply(context, args);
      lastTime = Date.now();
      inThrottle = true;
    } else {
      clearTimeout(lastFn);
      lastFn = setTimeout(function() {
        if (Date.now() - lastTime >= wait) {
          fn.apply(context, args);
          lastTime = Date.now();
        }
      }, wait - (Date.now() - lastTime));
    }
  };
};

参考链接:
脚本之家:debounce与throttle的简单版
博客:debounce与throttle的深入版
掘金: 函数节流与函数防抖
debounce 与throttle 的适用场景
奇舞周刊的总结

你可能感兴趣的:(函数节流与函数防抖)