可配置防抖函数支持 immediate 模式(首次立即执行,冷却期内忽略后续调用)和标准模式(延迟执行最后一次),通过 timer 状态与 immediate 参数协同控制执行时机,并提供 cancel 方法。

可配置的防抖函数需要支持 immediate 模式(即首次调用立即执行,后续触发在冷却期内被忽略),同时保留标准防抖行为(延迟执行最后一次)。关键在于区分两种模式下的定时器管理与执行时机控制。
理解 immediate 模式的行为逻辑
在 immediate 模式下:
- 第一次调用函数时,立刻执行回调,不等待;
- 之后在 wait 毫秒内再次触发,会被忽略(不执行,也不重置);
- wait 时间过后,若再次触发,则重新进入 immediate 流程(即又立刻执行一次)。
这与标准防抖(始终延迟、以最后一次为准)形成互补,适用于按钮点击防重复提交、搜索框首次快速响应等场景。
核心实现:用标志位 + 定时器协同控制
需维护两个关键状态:
- timer:存储当前 setTimeout 句柄,用于清除;
- isImmediatePending(或类似标志):标记“是否刚进入 immediate 状态且仍在冷却中”。
更简洁的做法是:不额外设标志位,而是通过 timer 是否为 null + immediate 参数组合判断。例如:
当 immediate 为 true 时,首次调用直接执行,并设置 timer 延迟清除“冷却态”;后续调用若 timer 存在,说明还在冷却期,直接跳过。完整可配置防抖函数示例
以下是一个兼顾 immediate、可取消、支持 this 和参数透传的实现:
function debounce(func, wait, immediate = false) {
let timer = null;
const debounced = function(...args) {
const later = () => {
if (!immediate) func.apply(this, args);
timer = null;
};
const callNow = immediate && !timer;
if (callNow) func.apply(this, args);
clearTimeout(timer);
timer = setTimeout(later, wait);
};
debounced.cancel = () => {
clearTimeout(timer);
timer = null;
};
return debounced;
}
说明:
- callNow 判断确保:immediate 为真 + 当前无活跃 timer → 才立即执行;
- 每次调用都 clearTimeout,保证旧任务不干扰;
- later 中只在 !immediate 时执行 func,避免重复调用;
- cancel 方法提供手动清理能力,便于测试或生命周期管理。
使用时注意 this 和参数绑定
该实现已用 func.apply(this, args) 正确传递上下文和参数。如需预绑定,建议在调用 debounce 时处理:
- ❌ 错误:
debounce(obj.method, 300)—— this 会丢失; - ✅ 正确:
debounce(() => obj.method(), 300)或debounce(obj.method.bind(obj), 300); - ✅ 更推荐:
debounce(obj.method, 300).bind(obj)(但注意 bind 后 cancel 需从原函数访问)。
实际项目中,常配合 React useCallback 或 Vue 的 watch handler 封装,确保引用稳定。











