防抖和节流是解决不同问题的明确方案:防抖管“结果要不要”,节流管“过程匀不匀”;二者均依赖闭包保存状态,但逻辑不同——防抖重置延迟、等待停止后执行,适用于输入完成类场景;节流定时放行、固定频率执行,适用于持续响应类场景。

防抖和节流不是“差不多”的优化手段,而是解决两类不同问题的明确方案:一个管“结果要不要”,一个管“过程匀不匀”。它们都依赖闭包来保存状态(比如定时器或时间戳),但逻辑走向完全不同。
防抖:等你彻底停手再执行
核心是“重置+延迟”。每次事件触发,就清除旧定时器、新建一个;只有最后一次触发后的等待期完整走完,函数才真正运行。
- 适合需要最终值的场景:用户输入完成、窗口调整完毕、表单内容稳定后才校验或保存
- 典型例子:搜索框输入——打“前端开发”5个字,中间不停顿,只在最后停顿300ms后发一次请求,不是5次
- 闭包作用:让timer变量私有化,避免多个防抖实例互相干扰。同一个debounce(fn, 300)调用返回的函数,各自维护自己的定时器
节流:按固定节奏稳稳执行
核心是“守时+放行”。不管事件多密,只要到了设定的时间点(比如每200ms),就允许执行一次,其余触发直接忽略。
- 适合需要持续响应但不能太猛的场景:滚动加载更多、鼠标移动轨迹采集、按钮防连点
- 典型例子:无限滚动——用户快速滑动页面,scroll事件每毫秒可能触发十几次,但节流后每300ms最多执行一次数据加载逻辑
- 闭包作用:封装lastTime或canRun这类状态,确保每次调用都能读取并更新上一次执行的时间或锁态
怎么一眼挑对?看事件性质
不用死记场景,抓住两个关键词判断:
- 输入类事件(input、keyup、change)→ 优先防抖:你要的是用户“写完”之后的内容,不是他敲每个键的过程
- 位移/状态类事件(scroll、resize、mousemove、click)→ 优先节流:你要的是“过程中”的反馈,比如滚动位置、窗口尺寸、点击节奏,不是只关心最后一次
- 例外提醒:按钮点击有时也用防抖(比如提交后禁用按钮+延时恢复),但本质仍是防止“重复提交”这个结果,不是响应点击过程
闭包不是炫技,是必须
没有闭包,防抖的timer会全局共享,节流的lastTime会串场。所有实际项目里的防抖/节流函数,都是返回一个闭包函数——它把原始函数、延迟参数、内部状态全“封”在一起,各自独立运行,互不污染。











