【JavaScript】✨防抖 vs 节流:给疯狂点击加上「冷静期」与「节奏感」

63 阅读2分钟

1. 前言 ✨

在前端开发中,防抖(Debounce)和节流(Throttle)是两种常用的性能优化技术,用于处理频繁触发的事件(如表单提交、输入框输入、窗口 resize 等),避免因事件触发过于密集而导致的性能问题。下面我们用 console.log() 模拟一个表单提交场景:

当用户重复点击提交按钮时,数据会不断提交,这将显著增加服务器负担。如何解决这个问题呢?让我们一起进入今天的主题。

2. 防抖(Debounce)✨

2.1 概念 ⚡

防抖是指当事件被频繁触发时,不立即执行回调,而是等待事件停止触发后经过指定时间才执行一次。若在等待期间事件被再次触发,则重新计时。其核心思想是:在规定的等待时间内没有新触发,才执行回调

2.2 原理 ⚙️

  1. 事件触发时设置延迟定时器
  2. 若在延迟期间再次触发,则清除旧定时器并重置延迟
  3. 延迟结束后执行回调

2.3 代码实现 💻

btn.addEventListener("click", debounce(submit, 2000));

function debounce(fn, delay) {
  let timer = null;
  return function (...args) {
    clearTimeout(timer); // 清除上次的定时器
    timer = setTimeout(() => {
      fn.call(this, ...args); // 延迟结束后执行
    }, delay);
  };
}

3. 节流(Throttle)✨

3.1 概念 ⚡

节流是指控制事件触发频率,确保回调函数在规定时间内只执行一次。其核心思想是:固定时间间隔内仅响应一次事件触发

3.2 原理 ⚙️

  1. 事件触发时,若未进入冷却期则立即执行回调并进入冷却
  2. 冷却期内再次触发事件则被忽略
  3. 冷却期结束后可再次响应

3.3 代码实现 💻

方案1:定时器实现

function throttle(fn, delay) {
  let timer = null;
  return function (...args) {
    if (!timer) { // 若无定时器则执行
      timer = setTimeout(() => {
        fn(...args);
        timer = null; // 执行后释放定时器
      }, delay);
    }
  };
}

方案2:时间戳实现

function throttle(fn, delay) {
  let prevTime = 0; // 记录上次执行时间
  return function (...args) {
    const now = Date.now();
    if (now - prevTime >= delay) { // 达到时间间隔
      fn(...args);
      prevTime = now; // 更新执行时间
    }
  };
}

4. 防抖和节流的区别 ✨

防抖(Debounce)节流(Throttle)
核心思想响应事件停止触发后的最后一次操作固定时间间隔内仅响应一次
效果高频操作后只执行一次有节奏地执行,按固定频率响应
使用场景输入联想搜索、窗口 resize 事件、按钮防重复提交游戏射击按钮、滚动加载、鼠标拖拽操作