javascript 中的防抖(debounce)和节流(throttle)通过控制函数执行的频率来支持时间窗口。核心做法是记录上一次执行的时间戳,在每次触发时计算当前时间与上次执行时间的差值,若差值大于设定的时间窗口则允许执行并更新时间戳,否则忽略本次触发。

如何实现基于时间戳的防抖
实现防抖的关键在于使用闭包保存状态,并在定时器回调中重置或保留该状态。以下代码展示了最基础的防抖实现,它会在事件停止触发后的指定毫秒数后执行一次函数。

function debounce(func, wait) {
let timeout;
return function(...args) {
const context = this;
clearTimeout(timeout);
timeout = setTimeout(() => {
func.apply(context, args);
}, wait);
};
}
上述代码中,每次调用返回的函数都会清除之前的定时器,并设置一个新的定时器。只有当连续触发间隔超过 wait 时间时,内部的 func 才会真正执行。这种实现方式适用于搜索框输入等场景,能有效减少不必要的 API 请求。
如何实现基于时间戳的节流
节流的实现逻辑与防抖不同,它关注的是在固定时间窗口内只执行一次函数。通常的做法是记录上一次执行的时间,如果当前时间减去上次执行时间小于阈值,则跳过本次执行;否则执行函数并更新上次执行时间。

function throttle(func, wait) {
let previous = 0;
return function(...args) {
const now = Date.now();
const context = this;
if (now - previous > wait) {
previous = now;
func.apply(context, args);
}
};
}
在这个实现中,Date.now() 用于获取当前时间戳。通过比较 now - previous 与 wait 的大小关系,确保在任意 wait 时间段内,函数最多只执行一次。这种方式常用于窗口滚动、鼠标移动等高频事件,以平衡性能与用户体验。
如何处理防抖中的立即执行选项
在实际开发中,有时需要在第一次触发时就立即执行函数,而不是等待时间窗口结束。这可以通过添加一个 immediate 参数来实现。当 immediate 为 true 时,首次触发会立即执行,随后的触发则会进入正常的防抖逻辑。
function debounceImmediate(func, wait, immediate) {
let timeout;
return function(...args) {
const context = this;
const callNow = immediate && !timeout;
clearTimeout(timeout);
if (callNow) {
func.apply(context, args);
} else {
timeout = setTimeout(() => {
timeout = null;
if (!immediate) {
func.apply(context, args);
}
}, wait);
}
};
}
这个增强版的防抖函数增加了灵活性。当 immediate 为真时,callNow 变量会在首次调用时为 true,从而立即执行函数。同时,定时器被重置,后续的触发将不再立即执行,而是等待下一个时间窗口。这种模式适用于按钮点击防止重复提交等场景,既能保证即时反馈,又能防止用户快速多次点击导致的问题。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











