闭包在节流函数中持久化保存上一次执行的时间戳,使内层函数能通过比较当前时间与该时间戳的差值决定是否执行;它避免全局变量,靠嵌套函数引用外层变量实现状态私有化与跨调用共享。

闭包在实现节流(throttle)函数时,核心作用是**持久化保存上一次执行的时间戳**,从而在后续调用中能与当前时间比较差值,决定是否放行执行。它不依赖全局变量,也不污染外部作用域,靠函数嵌套 + 内部函数引用外层变量来达成。
闭包如何捕获并维护时间戳
节流函数通常返回一个包装后的函数,这个函数能访问外层函数作用域中定义的 previous(或 lastTime)变量。该变量在闭包中被“记住”,每次调用都不重置:
- 外层函数(如
throttle(fn, delay))执行一次,初始化let previous = 0 - 返回的内层函数(事件回调)每次运行时,都能读写这个
previous - 即使外层函数已执行完毕,
previous仍保留在内存中,供内层函数持续使用
典型节流实现(基于时间戳差值)
以下是一个使用闭包记录时间戳、通过差值控制执行频率的节流函数:
function throttle(fn, delay) {
let previous = 0; // 闭包变量:记录上一次真正执行的时间戳
return function(...args) {
const now = Date.now();
if (now - previous >= delay) {
fn.apply(this, args);
previous = now; // 更新时间戳,为下一次判断做准备
}
};
}
使用示例:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
const handleScroll = throttle(() => {
console.log('滚动处理', Date.now());
}, 300);
<p>window.addEventListener('scroll', handleScroll);</p>
这里 previous 就是靠闭包维持的状态——每次 handleScroll 被触发,都共享同一个 previous,无需额外参数或全局变量。
为什么不用 setInterval 或 setTimeout 模拟?
单纯用定时器无法自然记录“上一次执行时间”,容易出现竞态或逻辑错乱。而闭包配合 Date.now() 的方式更轻量、精准且可预测:
- 不依赖异步队列调度,避免定时器延迟累积
- 每次判断基于真实流逝时间(
now - previous),不是固定间隔唤醒 - 闭包让
previous成为私有状态,多个节流实例互不影响
注意点:this 和参数的正确传递
闭包本身不自动绑定 this 或参数,需显式处理:
- 用
fn.apply(this, args)确保原函数的this和参数正确传递 - 若需支持取消节流(如清理状态),可在闭包中暴露方法,或返回带
cancel的对象 - 某些场景需兼容首次立即执行(leading edge),这时闭包还需维护一个
firstCall标志位
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










