手写防抖和节流

🚀 一、防抖(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

  • 动画优化


🧠 最后一招(面试收尾)

👉 你可以这样总结:

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


相关推荐
程序员Sunday6 小时前
JavaScript 事件循环面试题,宏任务与微任务怎么执行|Sunday面试指南
开发语言·javascript·面试·校招·事件循环·程序员sunday
Setsuna_F_Seiei6 小时前
前端转型 Agent 开发 06 之 Agent Memory 记忆系统(让 Agent 更智能,更懂你)
前端·agent·ai编程
zhangzeyuaaa7 小时前
Ruby 多线程、GVL(GIL)与 Mutex 完全指南
开发语言·前端·ruby
默_笙8 小时前
🌊 向量库和 ES 都查不出"关系",我只好给奶茶建了一张人脉网
前端·javascript
优选资讯8 小时前
标签打印软件怎么对接 Excel 数据
前端·excel
思无邪668 小时前
用 AI 做 JS 逆向:从抓包到复现的完整方法论
开发语言·javascript·人工智能
一个风轻云淡9 小时前
GCC 和 GDB命令简单解读
java·linux·前端
u01110267510 小时前
图片处理接口如何统一错误信息 前端提示与后端错误码设计
前端·状态模式
福兮说10 小时前
浏览器里把 iPhone 的 HEIC 转成 JPG:Chrome 解不开、转完大了七成、拍摄时间全丢,六个坑实测
前端·javascript·图像处理·chrome·ios·iphone·heic
libokaifa10 小时前
把语音模型塞进手机:sherpa-onnx 在 Android 上的 ASR / TTS
前端