手写防抖和节流

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

  • 动画优化


🧠 最后一招(面试收尾)

👉 你可以这样总结:

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


相关推荐
陆枫Larry10 小时前
可滚动页面背景填不满:`height: 100vh` vs `min-height: 100vh`
前端
Patrick_Wilson11 小时前
Squash Merge 的血缘陷阱:为什么删掉的代码又活了过来
前端·git·程序员
kyriewen11 小时前
今天的科技圈,全在抢英伟达的饭碗
前端·面试·ai编程
SouthernWind11 小时前
RAGFlow——结合本地知识库检索开发实战指南(包含聊天、检索本地的知识库文档和Agent模式)
前端
三翼鸟数字化技术团队12 小时前
websocket及SSE原理解析
前端
妙码生花12 小时前
从 PHP 到 AI + Golang,程序员自救转型手记(八):设计管理员模型、热重载配置
前端·后端·go
政采云技术12 小时前
Chrome 高阶调试技巧
前端
牧艺12 小时前
HTML-in-Canvas 深度解析:让 Canvas 真正「吃上」HTML 这碗饭
前端·html·canvas
秦瑜华12 小时前
前端页面添加AI自动翻译按钮
前端·openai·ai编程