手写防抖和节流

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

  • 动画优化


🧠 最后一招(面试收尾)

👉 你可以这样总结:

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


相关推荐
|晴 天|2 小时前
Vue 3 + TypeScript + Element Plus 博客系统开发总结与思考
前端·vue.js·typescript
猫3283 小时前
v-cloak
前端·javascript·vue.js
AC赳赳老秦3 小时前
OpenClaw二次开发实战:编写专属办公自动化技能,适配个性化需求
linux·javascript·人工智能·python·django·测试用例·openclaw
旷世奇才李先生3 小时前
Vue 3\+Vite\+Pinia实战:企业级前端项目架构设计
前端·javascript·vue.js
Ulyanov4 小时前
《PySide6 GUI开发指南:QML核心与实践》 第二篇:QML语法精要——构建声明式UI的基础
java·开发语言·javascript·python·ui·gui·雷达电子对抗系统仿真
聚美智数4 小时前
企业实际控制人查询-公司实控人查询
android·java·javascript
SoaringHeart4 小时前
Flutter进阶:用OverlayEntry 实现所有弹窗效果
前端·flutter
IT_陈寒6 小时前
Vite静态资源加载把我坑惨了
前端·人工智能·后端
herinspace6 小时前
管家婆实用贴-如何分离和附加数据库
开发语言·前端·javascript·数据库·语音识别
小码哥_常7 小时前
从MVC到MVI:一文吃透架构模式进化史
前端