JS 入门通关手册(38):防抖与节流 原理 + 手写 + 实战场景(面试必考)

摘要

本文详细讲解前端高频面试与实战核心知识点 ------ 防抖和节流。从概念、原理、区别入手,提供可直接用于生产环境的手写代码,并结合搜索框、滚动加载、窗口 resize、按钮点击等真实业务场景演示用法,帮助你彻底掌握性能优化必备技能。


一、为什么要使用防抖与节流?

在前端开发中,像 scrollresizeinputmousemoveclick 这类事件触发频率极高。如果每次触发都执行复杂逻辑(AJAX、DOM 操作、计算),会严重占用资源,导致页面卡顿、接口请求泛滥。

防抖与节流就是为了控制高频事件的执行次数,做性能优化。


二、防抖(Debounce)

1. 概念

触发高频事件后,延迟 n 秒再执行函数; 如果 n 秒内再次触发,则重新计时。

一句话记忆:**"等你停了,我再执行"**典型场景:搜索框输入联想。

2. 手写基础防抖

javascript

运行

javascript 复制代码
function debounce(fn, delay = 300) {
  let timer = null;
  return function (...args) {
    // 再次触发时清除上一次定时器
    if (timer) clearTimeout(timer);
    timer = setTimeout(() => {
      fn.apply(this, args);
    }, delay);
  };
}

3. 立即执行版本(可选)

有些场景希望第一次触发立即执行,后续频繁触发不执行:

javascript

运行

javascript 复制代码
function debounce(fn, delay = 300, immediate = false) {
  let timer = null;
  return function (...args) {
    if (timer) clearTimeout(timer);

    // 立即执行
    if (immediate && !timer) {
      fn.apply(this, args);
    }

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

4. 防抖适用场景

  • 搜索框输入联想(input)
  • 表单验证(手机号、邮箱校验)
  • 窗口大小变化 resize
  • 鼠标移动 mousemove
  • 频繁点击按钮防止重复请求

三、节流(Throttle)

1. 概念

高频事件触发时,保证在 n 秒内只执行一次 **。无论触发多快,都按固定频率执行。**

一句话记忆:**"冷却时间,到点才能放技能"**典型场景:滚动加载、下拉刷新。

2. 时间戳版节流(立即执行)

javascript

运行

javascript 复制代码
function throttle(fn, interval = 300) {
  let lastTime = 0;
  return function (...args) {
    const now = Date.now();
    if (now - lastTime >= interval) {
      fn.apply(this, args);
      lastTime = now;
    }
  };
}

3. 定时器版节流(延迟执行)

javascript

运行

javascript 复制代码
function throttle(fn, interval = 300) {
  let timer = null;
  return function (...args) {
    if (!timer) {
      timer = setTimeout(() => {
        fn.apply(this, args);
        timer = null;
      }, interval);
    }
  };
}

4. 节流适用场景

  • 滚动加载更多(scroll)
  • 高频点击抢购、投票
  • 鼠标拖拽、绘图
  • 游戏技能冷却
  • 视频播放时间更新

四、防抖 vs 节流 核心区别

表格

特性 防抖 Debounce 节流 Throttle
核心思想 最后一次才执行 固定频率执行
执行次数 多次触发 → 一次执行 多次触发 → 均匀执行
口诀 停了再执行 冷却再执行
典型场景 搜索输入、表单校验 滚动加载、点击限流

一句话区分:

  • 防抖:只认最后一次
  • 节流:均匀执行

五、真实业务使用示例

1. 搜索框防抖

javascript

运行

javascript 复制代码
const input = document.querySelector("#search");
input.oninput = debounce(() => {
  console.log("发起搜索请求");
}, 500);

2. 滚动节流加载

javascript

运行

javascript 复制代码
window.onscroll = throttle(() => {
  console.log("滚动加载数据");
}, 800);

六、高频面试题

  1. **防抖和节流的区别是什么?**答:防抖是多次触发只执行最后一次;节流是在固定时间内只执行一次,均匀限流。

  2. **分别适用什么场景?**答:防抖用于输入、resize;节流用于滚动、点击、拖拽。

  3. **手写防抖 / 节流要注意什么?**答:保存定时器 / 时间戳、返回闭包、绑定 this、传递参数。

  4. **节流时间戳和定时器版本区别?**答:时间戳版立即执行,定时器版延迟执行。

  5. **Vue/React 中使用要注意什么?**答:注意防抖节流函数只初始化一次,不要放在 render 内重复生成。


七、工程实践建议

  1. 搜索输入、表单校验 → 防抖
  2. 滚动加载、高频点击 → 节流
  3. 延迟优先 300~500ms
  4. 项目中可直接使用 Lodash:_.debounce / _.throttle
  5. 面试必须能手写最简版本

七、总结

  1. 防抖:高频触发 → 等待停止 → 执行最后一次
  2. 节流:高频触发 → 固定频率 → 均匀执行
  3. 防抖适合 "停止后执行",节流适合 "持续触发限流"
  4. 两者都是前端性能优化必备手段
  5. 手写核心:闭包保存定时器 / 时间戳,控制执行时机
相关推荐
weixin_4316004435 分钟前
前端数据埋点(7):Web Vitals——页面慢不慢,不是再包一层 fetch
前端·性能优化·sentry·数据埋点
এ慕ོ冬℘゜2 小时前
前端实战:jQuery实现动态表格渲染与状态切换功能
前端·javascript·jquery
zzzzzz3102 小时前
react-bits:把酷炫动效从“灵感截图”变成可复用的 React 组件
javascript·react.js·动效
海兰9 小时前
【应用】基于 Next.js 16 + Python mplfinance的金融K线图与技术指标可视化平台(三)
javascript·python·金融
小磊哥er11 小时前
深入解构Claude Code - 第 7 篇 · 连接外面的世界
javascript·ai编程
小磊哥er11 小时前
深入解构Claude Code - 第 6 篇 · 终端里的图形界面
javascript·ai编程
海兰11 小时前
【应用】基于 Next.js 16 + Python mplfinance的金融K线图与技术指标可视化平台(一)
javascript·python·金融
可乐鸡翅yeah_13 小时前
hls.js 内存泄漏实战排查,直播 M3U8 长时间播放异常定位方案
开发语言·javascript·python·django·ecmascript·m3u8·m3u8在线
可乐鸡翅yeah_13 小时前
第三方接口对接 M3U8 流媒体排坑实战,解决外部服务商流兼容难题
前端·javascript·python·django·html·m3u8·m3u8在线
默_笙13 小时前
🏠 「LLM Notes」:我用 Next.js + Redis 给自己造了个笔记博客
前端·javascript