防抖和节流应根据交互意图选择:防抖适用于“等稳了再干”,如搜索输入、表单验证;节流适用于“匀速地干”,如滚动监听、鼠标跟踪。两者核心逻辑、典型场景及工程实践要点均需精准匹配业务需求。

防抖和节流不是“选一个用”,而是根据交互意图决定用哪个——关键看你要的是“等稳了再干”,还是“匀速地干”。
防抖:适合“收尾确认”类操作
当用户行为有明确终点(比如打完字、调完窗、点完按钮),且你只关心最终状态时,就用防抖。它会把一连串触发压缩成一次执行,避免中间冗余。
- 典型场景:搜索框输入联想、窗口 resize 后重排布局、表单失焦验证、防止按钮重复提交
- 核心逻辑:每次触发都重置倒计时;只有连续静默超过设定毫秒,才真正执行
-
基础写法:
function debounce(fn, delay) { let timer; return function(...args) { clearTimeout(timer); timer = setTimeout(() => fn.apply(this, args), delay); }; } - 实用建议:搜索建议常用 300–500ms;表单校验可设 200ms;按钮防重复建议带立即执行选项(首次点击立刻生效,后续防抖)
节流:适合“持续反馈”类操作
当需要在高频动作中保持一定节奏的响应(比如滚动加载、鼠标跟随、实时位置上报),就要用节流。它保证函数不会太密,但也不会完全跳过中间过程。
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 典型场景:页面滚动监听(如懒加载、吸顶)、mousemove 跟踪、resize 中动态计算宽高比
- 核心逻辑:要么靠时间戳比对上次执行时间,要么靠定时器锁定执行窗口;确保单位时间内最多执行一次
-
时间戳版(推荐):
function throttle(fn, delay) { let lastTime = 0; return function(...args) { const now = Date.now(); if (now - lastTime >= delay) { fn.apply(this, args); lastTime = now; } }; } - 实用建议:滚动监听常用 16–60ms(匹配帧率);mousemove 可设 32ms;避免设低于 16ms,否则可能比渲染还快,反而增加负担
别踩这些坑
写得出来不等于用得对。几个容易忽略但影响实际效果的细节:
-
this 和参数丢失:务必用
fn.apply(this, args)或箭头函数 + 展开运算符,别直接fn(...args)(会丢 this) - 闭包变量污染:每个防抖/节流函数应独立维护自己的 timer 或 lastTime,不要共用全局变量
-
没清理定时器:组件卸载或事件解绑前,记得调用
clearTimeout(timer)(防抖)或清空状态(节流),避免内存泄漏 -
混淆 immediate 模式:防抖加
immediate: true是“首触即执行,后续等静默”,不是“每次都立刻执行”
工程中怎么选更省心
业务代码里手写没问题,但大型项目建议统一管理:
- 用 Lodash:直接
_.debounce(fn, 300)或_.throttle(fn, 100),自带取消、刷新、leading/trailing 控制 - 封装 Hook(React):写
useDebounce(value, delay)或useThrottleCallback(fn, delay),自动处理依赖和清理 - Vue 3 可结合
watch的flush: 'post'+nextTick做轻量防抖,或用lodash-es按需引入
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










