手写防抖和节流

🚀 一、防抖(debounce)

👉 核心:只执行最后一次


✍️ 基础版

复制代码
function debounce(fn, delay) {
  let timer = null;

  return function (...args) {
    if (timer) clearTimeout(timer);

    timer = setTimeout(() => {
      fn.apply(this, args);
    }, delay);
  };
}

🔥 进阶版(立即执行 + 可取消)

👉 面试建议写这个

复制代码
function debounce(fn, delay, immediate = false) {
  let timer = null;

  function debounced(...args) {
    const callNow = immediate && !timer;

    if (timer) clearTimeout(timer);

    timer = setTimeout(() => {
      timer = null;
    }, delay);

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

  debounced.cancel = function () {
    if (timer) {
      clearTimeout(timer);
      timer = null;
    }
  };

  return debounced;
}

🧠 你要会讲

👉 一句话:

防抖通过不断清除定时器,让函数只在"最后一次触发后"执行。

👉 场景:

  • input 搜索

  • resize

  • 按钮防重复提交


🚀 二、节流(throttle)

👉 核心:单位时间内只执行一次


✍️ 时间戳版(简单)

复制代码
function throttle(fn, delay) {
  let lastTime = 0;

  return function (...args) {
    const now = Date.now();

    if (now - lastTime > delay) {
      fn.apply(this, args);
      lastTime = now;
    }
  };
}

✍️ 定时器版

复制代码
function throttle(fn, delay) {
  let timer = null;

  return function (...args) {
    if (timer) return;

    timer = setTimeout(() => {
      fn.apply(this, args);
      timer = null;
    }, delay);
  };
}

🔥 高级版(推荐写)

👉 支持"首尾执行"(大厂常问)

复制代码
function throttle(fn, delay) {
  let lastTime = 0;
  let timer = null;

  return function (...args) {
    const now = Date.now();
    const remaining = delay - (now - lastTime);

    if (remaining <= 0) {
      if (timer) {
        clearTimeout(timer);
        timer = null;
      }

      fn.apply(this, args);
      lastTime = now;
    } else if (!timer) {
      timer = setTimeout(() => {
        fn.apply(this, args);
        lastTime = Date.now();
        timer = null;
      }, remaining);
    }
  };
}

🧠 你要会讲

👉 一句话:

节流通过控制时间间隔,让函数按固定频率执行。

👉 场景:

  • scroll

  • 页面拖拽

  • mousemove


⚔️ 三、面试必问对比

防抖 节流
执行时机 最后一次 按频率
是否会丢事件 不会
适用场景 输入框 滚动

🔥 四、面试加分点(你这个级别必须说)

✅ 1. 本质

都是通过 闭包保存状态 + 定时器控制执行


✅ 2. this 和参数

复制代码
fn.apply(this, args)

👉 不写这个会被扣分


✅ 3. requestAnimationFrame 节流(高级)

复制代码
function throttleRAF(fn) {
  let lock = false;

  return function (...args) {
    if (lock) return;

    lock = true;

    requestAnimationFrame(() => {
      fn.apply(this, args);
      lock = false;
    });
  };
}

👉 更适合:

  • scroll

  • 动画优化


🧠 最后一招(面试收尾)

👉 你可以这样总结:

防抖是控制"最后一次执行",节流是控制"执行频率",两者本质都是利用闭包和定时器来优化高频事件性能。


相关推荐
To_OC8 小时前
别再瞎写 React Router!7 个高频踩坑点一次性讲透
前端·javascript·react.js
岭南灯火10 小时前
前端通用交互式几何编辑器的开发经验
前端·设计模式·架构
岭南灯火10 小时前
前端通用交互式几何编辑器的设计法则 7 - 设计模式与原则
前端·设计模式·架构
岭南灯火10 小时前
前端通用交互式几何编辑器的设计法则 4 - 绘制、悬停与编辑
前端·设计模式·架构
岭南灯火10 小时前
前端通用交互式几何编辑器的设计法则 3 - 数据对象的设计
前端·javascript·架构
Jackson__10 小时前
从 LLM 到 Agent:一篇文章搞懂 AI 圈热词!
前端·agent·ai编程
岭南灯火10 小时前
前端通用交互式几何编辑器的设计法则 2 - 交互事件流
前端·javascript·架构
岭南灯火10 小时前
前端通用交互式几何编辑器的设计法则 6 - 配套设施与工程化
前端·设计模式·架构
岭南灯火10 小时前
前端通用交互式几何编辑器的设计法则 5 - 辅助元素的设计
前端·设计模式·架构
岭南灯火10 小时前
前端通用交互式几何编辑器的设计法则 1 - 入口的对象及其成员
前端·javascript·架构