👨‍💻 BitPeng

📰 JavaScript 防抖函数学习笔记(Debounce)

创建于 2025-05-20 09:17:27

修改于 2025-05-20 09:17:27

一、什么是防抖(Debounce)

防抖(Debounce):一种控制函数执行频率的技术。
核心原理:某个函数在被频繁触发时,只有在 最后一次触发后的 N 秒内不再触发 才执行。


二、常见应用场景

场景说明
搜索框输入联想停止输入一段时间后发请求
窗口尺寸变化监听(resize)用户停止调整后再重新布局
按钮点击防连点防止用户连续点击多次

三、普通版防抖函数(不立即执行)

✅ 代码:

function debounce(fn, delay = 300) {
  let timer = null;

  return function (...args) {
    const context = this;

    clearTimeout(timer); // 清除上一次的定时器

    timer = setTimeout(() => {
      fn.apply(context, args); // 延迟执行函数
    }, delay);
  };
}

🧠 解析:

  • 每次调用都会 清除上一次的定时器
  • 然后重新设置一个新的定时器
  • 只有用户停止触发 delay 毫秒后,函数才会执行
  • 函数 fn 的上下文 this 和参数 args 都被正确保留

四、带立即执行的防抖函数(immediate = true)

✅ 代码:

function debounce(fn, delay = 300, immediate = false) {
  let timer = null;

  return function (...args) {
    const context = this;

    const callNow = immediate && !timer;

    clearTimeout(timer);

    timer = setTimeout(() => {
      timer = null;
      if (!immediate) {
        fn.apply(context, args);
      }
    }, delay);

    if (callNow) {
      fn.apply(context, args);
    }
  };
}

🧠 解析:

  • 增加了 immediate 参数,用于控制是否 第一次立即执行
  • callNow = immediate && !timer
    • 只有在 immediate = truetimer = null(冷却中)时,才会立即执行
  • timer = setTimeout(...) 会在延迟后将 timer 清空,使得下一次能再次立即执行
  • 如果 immediate = false,行为就和普通版本一样

五、行为对比说明

immediate 值首次触发多次连续触发停止触发后
false不执行一直清除定时器最后一次延迟后执行
true立即执行不再触发冷却后允许再次立即执行

六、使用示例

const log = () => console.log('触发');

const debounced = debounce(log, 1000, true);

debounced();            // 立即执行
setTimeout(debounced, 300);  // 忽略
setTimeout(debounced, 600);  // 忽略
setTimeout(debounced, 1100); // 间隔超时,重新立即执行

七、拓展:立即执行 + 最后一次触发也执行(高级需求)

function debounce(fn, delay = 300, immediate = false) {
  let timer = null;
  let called = false;

  return function (...args) {
    const context = this;

    if (immediate && !called) {
      fn.apply(context, args);
      called = true;
    }

    clearTimeout(timer);

    timer = setTimeout(() => {
      if (!immediate || !called) {
        fn.apply(context, args);
      }
      called = false;
    }, delay);
  };
}

✨ 特点:

  • 既能首次立即执行
  • 又能在最后一次触发后也执行一次(可选行为)

八、总结

  • 防抖用于减少频繁操作带来的性能问题
  • 关键点在于 clearTimeoutsetTimeout
  • 是否立即执行取决于 immediate 参数
  • 更复杂需求时可自行组合 首次触发 + 最后触发