防抖和节流本质是控制函数执行时机与频次:防抖适用于“等用户停下再响应”,如搜索输入、resize;节流适用于“定期响应不能全丢”,如滚动加载、鼠标追踪。

直接上手学,不绕弯——防抖和节流本质就两件事:什么时候执行、执行几次。掌握核心逻辑比死记代码更重要,下面分四块讲清楚,每块都聚焦真实开发中必须懂的关键点。
先分清场景:什么情况该用防抖?
防抖适用于等用户“停下来”再响应的场景。核心是“合并连续动作,只处理最终结果”。
- 搜索框输入:用户打字没停,就不发请求;停顿 300ms 后才查一次
- 窗口 resize:浏览器拖拽缩放时疯狂触发,等用户松手稳定后再重排布局
- 表单输入校验:输完邮箱再验证格式,不是每敲一个字符都跑一遍正则
记住口诀:“最后一次才动”。如果中间持续触发,函数永远不执行;只有彻底安静下来,才触发一次。
再看节流:什么情况必须用节流?
节流适用于必须定期响应、不能全丢掉的场景。核心是“固定节奏,稳住频率”。
- 滚动加载(infinite scroll):用户快速下滑,每 200ms 检测一次是否到底部,而不是等他停下才判断
- 鼠标移动追踪(如画板、拖拽):需要持续获取坐标,但不需要每像素都处理
- 按钮防重复点击:用户狂点,但只允许每 1 秒提交一次,避免重复下单
记住口诀:“再快也得匀着来”。哪怕事件每毫秒触发一次,函数也只按设定间隔执行,不会漏掉全部,也不会卡死主线程。
手写实现:从能用到靠谱
不用背源码,但要理解关键控制点:
- 防抖靠 clearTimeout + setTimeout:每次触发都清旧定时器、设新定时器;闭包保存 timer 变量是关键
-
节流两种主流写法:
- 时间戳版:记录上次执行时间,当前时间减去它 ≥ 间隔才执行(首次立即)
- 定时器版:用 setTimeout 控制“下一次可执行时机”,更易理解执行节奏
- 进阶必加:支持
this绑定、参数透传、立即执行模式(如按钮首次点击立刻生效)、取消功能(如组件卸载时清理定时器)
避坑与工程化要点
实际项目里,光会写还不够:
- 防抖设置 delay 太长(如 1s),用户会觉得响应迟钝;太短(如 50ms)又起不到优化效果,300–500ms 是常见平衡点
- 节流慎用在需要“首尾都响应”的场景(如动画起止),纯时间戳版不触发结尾,可结合定时器补尾调用
- Vue/React 中注意组件销毁时清除定时器,否则造成内存泄漏
- 优先用 Lodash 的
debounce/throttle,它们已处理边缘 case(如服务端渲染兼容、leading/trailing 配置)











