闭包实现限流与防刷的核心是利用闭包保存状态(如时间戳、定时器id),确保每个处理器实例独立可复用:限流固定频率执行,防刷延迟至静默期结束执行,增强版支持取消和立即执行。

用闭包实现限流(throttle)和防刷(debounce)事件处理器,核心是利用闭包保存状态(如上一次执行时间、定时器 ID、等待中的调用等),避免依赖全局变量,保证每个处理器实例独立、可复用。
限流(Throttle):固定频率执行
限流确保函数在指定时间间隔内最多执行一次,适合高频触发但只需定期响应的场景(如滚动监听、鼠标移动)。
闭包需记住:上次执行时间戳 和 是否处于冷却中。每次触发时判断距离上次执行是否超过阈值,是则立即执行并更新时间;否则忽略或排队(可选)。
示例实现:
function createThrottledHandler(fn, delay) {
let lastTime = 0;
return function(...args) {
const now = Date.now();
if (now - lastTime >= delay) {
fn.apply(this, args);
lastTime = now;
}
};
}
<p>// 使用
const handleScroll = createThrottledHandler(() => {
console.log('滚动处理中...');
}, 100);
window.addEventListener('scroll', handleScroll);</p>防刷(Debounce):延迟执行,重置计时
防刷让函数在连续触发后,只在“静默期”结束时执行一次,适合搜索建议、窗口缩放适配等需等待用户操作停止的场景。
闭包需保存:当前定时器 ID。每次触发先清除旧定时器,再设置新定时器,确保只有最后一次触发生效。
示例实现:
function createDebouncedHandler(fn, delay) {
let timerId = null;
return function(...args) {
clearTimeout(timerId);
timerId = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
}
<p>// 使用
const handleInput = createDebouncedHandler((e) => {
console.log('搜索关键词:', e.target.value);
}, 300);
input.addEventListener('input', handleInput);</p>增强版:支持取消与立即执行
实际项目中常需手动取消待执行任务,或首次触发立即执行(leading edge)、末次触发也执行(trailing edge)。可通过返回对象暴露控制方法。
关键点:闭包内维护 timerId 和 isPending 等状态,并提供 cancel() 和 flush() 方法。
简化版支持取消的防刷:
function createDebouncedHandler(fn, delay) {
let timerId = null;
const debounced = function(...args) {
clearTimeout(timerId);
timerId = setTimeout(() => {
fn.apply(this, args);
timerId = null;
}, delay);
};
debounced.cancel = () => {
clearTimeout(timerId);
timerId = null;
};
return debounced;
}
组合使用:一个处理器同时支持限流+防刷?
限流和防刷语义不同,一般不混用。但可封装为同一工厂函数,通过选项切换模式:
- mode: 'throttle' → 按时间间隔强制节制
- mode: 'debounce' → 按空闲期延迟聚合
- 内部共享闭包作用域,各自维护独立状态变量
这样既复用结构,又保持逻辑清晰,避免耦合。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











