防抖(debounce)是JavaScript中处理高频触发事件的常用优化方案,核心思路是在事件触发后等待一段时间,如果这段时间内没有再次触发事件,才执行目标函数;如果再次触发,则重新计时。这种方式能避免函数在短时间内被多次执行,减少不必要的计算和资源消耗。

防抖的基础实现
最基础的防抖实现只需要利用定时器,每次触发事件时先清除之前的定时器,再重新设置新的定时器。下面是基础版本的代码:
function debounce(func, delay) {
let timer = null;
return function(...args) {
// 清除之前的定时器,重新计时
if (timer) clearTimeout(timer);
// 设置新的定时器,delay时间后执行目标函数
timer = setTimeout(() => {
func.apply(this, args);
timer = null;
}, delay);
};
}这个版本的逻辑很清晰,返回的函数就是实际绑定到事件上的函数,每次调用时都会重置定时器,只有最后一次触发后等待delay时间没有新触发,才会执行func。
支持立即执行的防抖版本
有些场景下我们希望第一次触发事件时立即执行函数,之后在delay时间内再次触发则不执行,等delay时间过后再触发才会重新执行。这种需求可以通过添加一个是否立即执行的参数来实现:
function debounce(func, delay, immediate = false) {
let timer = null;
return function(...args) {
if (timer) clearTimeout(timer);
if (immediate) {
// 判断是否已经有定时器,没有的话说明是第一次触发或者已经过了等待期
const canExecute = !timer;
// 设置定时器,用于重置执行状态
timer = setTimeout(() => {
timer = null;
}, delay);
// 可以执行的话立即调用目标函数
if (canExecute) func.apply(this, args);
} else {
// 非立即执行版本,和之前的逻辑一致
timer = setTimeout(() => {
func.apply(this, args);
timer = null;
}, delay);
}
};
}防抖与函数节流的区别
很多开发者会混淆防抖和函数节流,两者的核心差异在于执行时机:
- 防抖是在事件停止触发后一段时间才执行,只执行最后一次触发的逻辑
- 函数节流是在固定时间间隔内只执行一次,不管事件触发了多少次
可以通过下面的表格更直观地对比两者的差异:
| 特性 | 防抖(debounce) | 函数节流(throttle) |
|---|---|---|
| 执行时机 | 事件停止触发后等待指定时间执行 | 固定时间间隔执行一次 |
| 执行次数 | 连续触发只执行最后一次 | 连续触发按间隔执行多次 |
| 适用场景 | 输入框搜索、表单验证、窗口resize适配 | 滚动加载、鼠标移动拖拽、页面滚动监听 |
防抖的实际使用场景
输入框搜索场景
用户在输入框输入内容时,不需要每次输入都发送搜索请求,而是在用户停止输入一段时间后再发送,减少请求次数:
// 模拟搜索请求函数
function search(keyword) {
console.log('发送搜索请求,关键词:', keyword);
}
// 创建防抖后的搜索函数,等待500毫秒执行
const debouncedSearch = debounce(search, 500);
// 获取输入框元素,绑定输入事件
const input = document.querySelector('input');
input.addEventListener('input', function(e) {
debouncedSearch(e.target.value);
});窗口resize适配场景
窗口大小改变时,不需要每次resize都重新计算布局,等用户调整完窗口大小后再执行适配逻辑:
// 布局适配函数
function adaptLayout() {
console.log('执行布局适配,当前窗口宽度:', window.innerWidth);
}
// 创建防抖后的适配函数,等待300毫秒执行
const debouncedAdapt = debounce(adaptLayout, 300);
// 监听窗口resize事件
window.addEventListener('resize', debouncedAdapt);注意事项
使用防抖时需要注意几个问题:
- 防抖返回的是一个新的函数,如果需要取消事件绑定,要保存这个返回的函数引用,不能直接用原函数取消
- 如果防抖函数内部用到了
this,需要通过apply或者call绑定正确的上下文,避免this指向错误 - delay时间需要根据实际场景调整,太短起不到优化效果,太长会影响用户体验
JavaScript防抖debounce函数节流修改时间:2026-06-05 01:57:10