防抖是“等静默”,节流是“控节奏”;防抖每次触发重置倒计时、只执行最后一次,适用于搜索、resize;节流固定间隔最多执行一次,适用于滚动、鼠标移动;二者均依赖闭包,但防抖维护timer,节流维护lasttime或valid。

掌握防抖与节流,关键不在死记代码,而在理解“事件节奏”和“函数执行时机”的关系。只要厘清触发逻辑、状态依赖和适用边界,手写实现和选型判断就自然清晰。
先分清核心行为模式
防抖是“等静默”,节流是“控节奏”——这是最本质的区分点。
- 防抖:每次新触发都重置倒计时,只响应最后一次“安静下来”的时刻。适合需要“最终结果”的场景,比如搜索关键词、窗口调整完再重排布局。
- 节流:不管你怎么点、怎么滚,每固定时间最多执行一次。适合需要“持续反馈但不泛滥”的场景,比如滚动监听位置、鼠标移动轨迹采样。
重点盯住两个实现依赖
两者都靠闭包维持状态,但维护的变量不同,这直接决定行为差异。
-
防抖必须存 timer:用
clearTimeout取消旧任务,setTimeout设置新任务。timer 是唯一判据,为空才说明上一轮已结束。 -
节流可存 lastTime 或 valid:时间戳版靠
Date.now()差值判断是否过冷却期;定时器版靠布尔标记(如valid)控制入口开关。二者逻辑等价,只是实现视角不同。
动手写时注意三个易错细节
这些地方不处理好,功能就容易失效或行为反直觉。
-
this 和参数要透传:返回的包装函数里,必须用
func.apply(this, arguments)或func(...args),否则上下文丢失、参数收不到。 -
立即执行模式要单独支持:防抖加
immediate参数,首次触发立刻执行,后续在 wait 内触发则重置;节流的时间戳版默认首调即执行,定时器版默认延迟执行——别混用。 -
清理机制不能遗漏:防抖中 timer 清除后应置为
null;节流中若用定时器方式,执行完需重置valid = true,否则锁死。
结合真实场景反向验证
脱离场景谈技术容易空转。拿一个典型例子反复推演:
- 用户在输入框连续敲
h-e-l-l-o,间隔 100ms,设防抖 300ms → 实际只触发 1 次,发生在敲完o后 300ms; - 同样操作设节流 300ms → 最多触发 2 次(比如第 1 次在敲
h时,第 2 次在敲l后 300ms),中间触发全部忽略。
能说清这个过程,说明你真正吃透了。











