防抖函数中immediate为true时首次触发立即执行,后续触发需等待冷却期结束;核心是用timeout状态标记判断是否处于冷却期,配合clearTimeout和setTimeout实现双模式逻辑。

防抖函数中处理 immediate 参数,核心是区分「首次触发立即执行、后续连续触发不执行,直到停止触发后重新计时」这种模式。它和默认的「等待停止触发后再执行」正好相反。
理解 immediate 的行为逻辑
当 immediate 为 true 时:
- 第一次调用函数时,立刻执行回调,不等待延迟
- 在延迟时间内再次触发,不会重复执行(已通过定时器或标志位拦截)
- 只有当「上一次执行完成 + 延迟时间过去后」,下一次触发才可再次立即执行
关键点在于:不能只靠一个定时器控制,必须配合状态标记(如 isPending 或 timeout 是否存在)来判断当前是否处于“冷却期”。
实现 immediate 的关键结构
典型写法需要两个分支逻辑:
- 若
immediate === true:检查是否已有待执行的定时器(即是否在冷却中)。没有就立即执行,并设置延迟定时器用于重置状态 - 若
immediate === false(默认):清除旧定时器,新建延迟执行定时器
常用状态变量包括:timeout(存储定时器 ID)、isCalling(标记是否刚执行过),二者选其一即可,推荐用 timeout 更直观。
一个简洁可靠的实现示例
// 返回防抖后的函数
function debounce(func, wait, immediate = false) {
let timeout = null;
return function executedFunction() {
const later = () => {
timeout = null;
if (!immediate) func.apply(this, arguments);
};
const shouldCallNow = immediate && !timeout;
if (shouldCallNow) func.apply(this, arguments);
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
说明:
-
shouldCallNow判断:仅当 immediate 为真且当前无 pending 定时器时,才首次立即执行 -
clearTimeout(timeout)每次都清,确保旧逻辑不干扰;新定时器统一由later收尾 -
later中只在非 immediate 模式下调用函数,避免重复执行
常见误区提醒
容易出错的地方:
- 误把
immediate当成「每次触发都立即执行」——实际它只对每个「稳定周期」的首次生效 - 未在
immediate分支里清除旧定时器,导致多次立即执行 - 用
!timeout判断时,忽略timeout初始为null和被清除后为null的一致性 - 忘记绑定
this和arguments,导致执行上下文丢失


















