
防抖(debounce)是什么,什么时候该用它
防抖是让一个函数在「连续触发」时,只执行最后一次。比如用户在搜索框里打字,你不想每按一次键就发一次请求,而是等他停顿 300ms 后再查——这就是典型的防抖场景。
关键判断点:你关心的是“操作结束后的结果”,而不是“过程中发生了什么”。常见于输入校验、窗口 resize 后重排布局、按钮重复点击拦截。
-
debounce函数内部通常用setTimeout+clearTimeout实现 - 每次新触发都会清掉前一次定时器,只保留最后一次的延时执行
- 注意:首次调用不会立刻执行,必须等间隔期过去;如果想“立即执行第一次,后续再防抖”,得用带
leading选项的版本
function debounce(fn, delay) {
let timer;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), delay);
};
}节流(throttle)怎么工作,和防抖的根本区别在哪
节流是限制函数「固定时间间隔内最多执行一次」。比如监听鼠标滚轮或拖拽事件,你想每 100ms 最多处理一次,避免高频回调压垮主线程。
核心差异:防抖会“攒”调用,节流会“匀速放行”。节流不关心你停不停,只要到了间隔时间点,就执行一次(哪怕中间触发了十次)。
立即学习“Java免费学习笔记(深入)”;
- 常见实现分两种:基于时间戳(首次立即执行)、基于定时器(首次延迟执行)
- 实际项目中推荐时间戳版,响应更及时;但要注意时间戳更新时机,别漏掉最后一次触发
- 某些 UI 库(如 Lodash)的
throttle默认启用trailing,即保证最后一次触发也会被执行,这点容易被忽略
function throttle(fn, limit) {
let lastCall = 0;
return function(...args) {
const now = Date.now();
if (now - lastCall >= limit) {
fn.apply(this, args);
lastCall = now;
}
};
}Vue/React 项目里怎么安全地加防抖节流
直接在组件方法里套 debounce 或 throttle 很容易出问题:组件卸载后定时器还在跑,this 指向丢失,甚至引发内存泄漏。
- Vue 2 中,建议在
beforeDestroy钩子中手动清除定时器(如果用了闭包保存 timer 引用) - Vue 3 的
setup中,用onBeforeUnmount清理;或者直接用lodash-es的debounce并配合ref存储实例 - React 函数组件必须用
useEffect清理,且不能把防抖函数写在 render 内部(否则每次渲染都新建,失去防抖意义);推荐封装成自定义 Hook,如useDebounceCallback - 注意:不要对箭头函数直接防抖,因为每次渲染都是新函数;要防抖的是稳定引用的方法
哪些坑会让防抖节流失效或变慢
最常踩的不是逻辑错,而是上下文和生命周期没管住。
- 把
debounce写在 React 的onClick里:onClick={debounce(handleClick, 300)}—— 每次渲染都新建防抖函数,等于没防 - 在 Vue 的
methods里直接返回debounce结果,但没绑定this,导致内部fn.apply(this)的this是undefined - 节流时间设太短(比如
16ms),在 60fps 下几乎没效果;设太长(如1000ms)又卡顿,需结合业务节奏调,输入类一般200–400ms,滚动类50–100ms - 服务端接口本身有缓存或限流,前端再防抖可能掩盖真实瓶颈,先确认问题在前端还是后端
防抖和节流不是万能胶,它们解决的是“调用频率失控”,而不是“逻辑错误”或“性能差”。用之前,先打开 DevTools 的 Performance 面板录一段操作,看瓶颈真正在哪。










