防抖函数的核心是等用户操作完全停止一段时间后执行一次回调,适合搜索输入、窗口缩放等场景;支持 immediate 参数控制首次是否立即执行,并需正确处理 this 和参数传递。

防抖函数的核心是:**等用户操作完全停止一段时间后,再执行一次回调**。它适合搜索框输入、窗口缩放、按钮连点等场景,避免函数被频繁调用。
防抖函数的基本实现
利用 setTimeout 延迟执行,并在每次新触发时清除之前的定时器:
function debounce(fn, delay) {
let timer = null;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
}
使用示例(监听输入框):
const searchInput = document.getElementById('search');
const debouncedSearch = debounce((value) => {
console.log('发起搜索:', value);
}, 300);
searchInput.addEventListener('input', (e) => {
debouncedSearch(e.target.value);
});
支持立即执行的防抖(leading edge)
有些场景需要首次触发立刻执行(比如页面加载后立刻响应一次),之后再进入“等待静默期”的逻辑。可加一个 immediate 参数控制:
function debounce(fn, delay, immediate = false) {
let timer = null;
return function (...args) {
const callNow = immediate && !timer;
clearTimeout(timer);
if (callNow) {
fn.apply(this, args);
}
timer = setTimeout(() => {
if (!immediate) {
fn.apply(this, args);
}
timer = null;
}, delay);
};
}
- 当 immediate: true,第一次输入立刻执行,后续输入仍按延迟执行
- 当 immediate: false(默认),只在停止输入后执行一次
注意 this 和参数的正确传递
防抖返回的是新函数,容易丢失原始调用上下文。上面实现中已用 fn.apply(this, args) 保证 this 和参数准确传递。若用箭头函数写法,需注意不能直接用 this,建议保留传统函数声明方式或显式绑定。
- 避免直接写
fn(...args)—— 会丢失this - 不推荐用
fn.bind(this, ...args)创建新函数再调用,效率低且易出错 - 若需在防抖函数内访问事件对象,确保在闭包中保存或传入
实际使用中的小技巧
防抖函数本身是纯逻辑,但集成到项目中要注意几点:
- 防抖函数应只创建一次,不要在事件监听器里反复调用
debounce(),否则每次都会新建定时器,失去防抖效果 - 组件卸载或监听器移除前,建议手动清理定时器(如将
timer暴露为返回函数的属性,或用 AbortController 管理) - 调试时可在
console.log中加时间戳,直观看到触发节奏是否符合预期
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











