手写防抖和节流

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

  • 动画优化


🧠 最后一招(面试收尾)

👉 你可以这样总结:

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


相关推荐
lUie INGA1 天前
rust web框架actix和axum比较
前端·人工智能·rust
OPHKVPS1 天前
VoidStealer新型窃密攻击:首例利用硬件断点绕过Chrome ABE防护,精准窃取v20_master_key
前端·chrome
月光宝盒造梦师1 天前
Ant Design Ellipsis 中的判断逻辑 isEleEllipsis 方法非常消耗性能
javascript·react·优化
gechunlian881 天前
SpringBoot3+Springdoc:v3api-docs可以访问,html无法访问的解决方法
前端·html
驾驭人生1 天前
ASP.NET Core 实现 SSE 服务器推送|生产级实战教程(含跨域 / Nginx / 前端完整代码)
服务器·前端·nginx
酉鬼女又兒1 天前
零基础快速入门前端ES6 核心特性详解:Set 数据结构与对象增强写法(可用于备赛蓝桥杯Web应用开发)
开发语言·前端·javascript·职场和发展·蓝桥杯·es6
慧一居士1 天前
Vue项目中,子组件调用父组件方法示例,以及如何传值示例,对比使用插槽和不使用插槽区别
前端·vue.js
我是伪码农1 天前
HTML和CSS复习
前端·css·html
林恒smileZAZ1 天前
前端实现进度条
前端
前端老石人1 天前
邂逅前端开发:从基础到实践的全景指南
开发语言·前端·html