节流函数的核心是用闭包缓存时间戳以控制执行频率:通过闭包持久化lasttime变量,每次调用对比date.now()与lasttime的差值,满足间隔才执行并更新时间戳,确保固定周期内最多执行一次,响应快且轻量。

节流函数(throttle)的核心是控制函数执行频率,而用闭包缓存时间戳,正是为了在多次调用中记住上一次执行的时刻。关键在于:闭包让内部函数能持续访问并更新外部作用域中定义的时间戳变量,无需依赖全局或 this 状态。
闭包保存上次执行时间戳
把 lastTime 声明在闭包外部(即返回函数的外层作用域),内部返回的节流函数就能反复读写它。每次调用时对比当前时间与 lastTime,决定是否放行。
- 时间戳初始值通常设为 0 或
Date.now(),表示尚未执行过 - 执行后立即更新
lastTime = Date.now(),下次调用才有参照 - 不使用
setTimeout或定时器队列,纯靠时间差判断,属于“时间戳版节流”
基础实现:带状态缓存的节流函数
以下是一个典型闭包结构的节流函数:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
function throttle(fn, delay) {
let lastTime = 0;
return function(...args) {
const now = Date.now();
if (now - lastTime >= delay) {
fn.apply(this, args);
lastTime = now;
}
};
}这里 lastTime 被闭包持久化,每次调用返回的函数都共享同一份变量。即使多次调用 throttle 创建不同节流器,每个都有独立的 lastTime,互不影响。
注意 this 和参数的正确传递
闭包本身不绑定 this,所以必须显式用 fn.apply(this, args) 或 fn.call(this, ...args) 保证原上下文和参数透传。
- 直接写
fn(...args)会丢失this,尤其在事件监听器中易出错 - 使用剩余参数
...args和展开语法,兼容任意数量的参数 - 如果需支持取消节流或重置状态,可额外暴露方法(如返回一个含
cancel和reset的对象)
和定时器节流的区别
时间戳节流响应快、无延迟累积,但“漏掉”的调用完全不执行;而 setTimeout 版会在延迟后强制执行最后一次触发(常称“尾部执行”)。两者适用场景不同:
- 滚动监听、鼠标移动等高频场景,优先选时间戳版,轻量且可控
- 需要确保“至少执行一次”的交互反馈(如按钮防抖+节流混合逻辑),才考虑定时器方案
- 闭包缓存的只是数字,不涉及异步任务调度,内存占用极小
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










