js防抖函数防抖无效的解决方法
在JavaScript中实现防抖函数:
// 正确传参的防抖实现
function debounce(func, delay) {
let timer;
return function(...args) { // 使用剩余参数接收所有传参
const context = this; // 保留函数执行上下文
clearTimeout(timer);
timer = setTimeout(() => {
func.apply(context, args); // 正确绑定this和传递参数
}, delay);
};
}
// 使用示例
const handleSearch = debounce(function(keyword) {
console.log('Searching:', keyword);
}, 500);
// 事件绑定(注意要直接使用返回的函数)
inputEl.addEventListener('input', (e) => {
handleSearch(e.target.value); // 直接调用已创建的防抖函数实例
});
但用户可能这样调用防抖函数:
// 错误示例
function handleInput(value) {
console.log(value);
}
function debouncedHandle(value) {
debounce(handleInput(value), 500);
}
input.addEventListener('input', (e) => debouncedHandle(e.target.value));
这会导致每次事件触发时都生成一个新的函数,而不是使用同一个防抖函数实例。这种情况下,定时器无法正确跟踪,防抖失效。
正确的做法应该是确保每次调用的是同一个防抖函数实例:
// 正确示例
function handleInput(value) {
console.log(value);
}
const debouncedHandle = debounce(handleInput, 500);
input.addEventListener('input', (e) => debouncedHandle(e.target.value));
这样,每次事件触发时都调用同一个debouncedHandle实例,参数会被正确传递,并且防抖逻辑有效。
关键点说明:
- 参数接收:使用剩余参数
...args
接收所有传入参数 - 上下文保存:通过闭包保存
this
上下文,避免箭头函数导致的上下文丢失 - 参数传递:使用
apply()
方法同时传递上下文和参数数组 - 实例保持:确保事件处理器中始终调用同一个防抖函数实例
建议将防抖函数实例存储在变量中重复使用,或在React/Vue等框架中使用useRef等Hook保持实例引用。