节流与防抖均依赖闭包保存timer或lastTime等私有状态,实现高频事件下的执行控制:防抖重置定时器、只执行最后一次;节流基于时间戳或定时器,确保固定间隔内最多执行一次。

节流(Throttle)和防抖(Debounce)都依赖闭包来保存状态(比如上一次执行时间、定时器 ID、等待中的回调等),让函数在高频触发时按需执行,避免资源浪费。核心在于:用闭包“记住”上次操作的时间或定时器,每次调用时根据规则决定是否执行或重置。
防抖函数:最后一次触发后延迟执行
适用于搜索框输入、窗口 resize 等场景——只关心最终结果,中间过程可忽略。
闭包保存 timer 变量,每次调用先清除旧定时器,再设新定时器:
function debounce(fn, delay) {
let timer = null;
return function (...args) {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
timer = null; // 可选:清空便于调试
}, delay);
};
}使用示例:
const search = debounce((query) => {
console.log('发起搜索:', query);
}, 300);
<p>input.addEventListener('input', (e) => search(e.target.value));</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill3430" title="Alibabacloud Sdk Client Initialization For Java"><img
src="https://img.php.cn/upload/skill/000/000/081/178955835420587.jpg" alt="Alibabacloud Sdk Client Initialization For Java" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill3430" title="Alibabacloud Sdk Client Initialization For Java" class="overflowclass">Alibabacloud Sdk Client Initialization For Java</a>
<p class="overflowclass">在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。</p>
</div>
<a rel="nofollow" href="/xiazai/skill3430" title="Alibabacloud Sdk Client Initialization For Java" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>节流函数:固定间隔内最多执行一次
适用于鼠标拖拽、滚动监听等——需要稳定节奏,但不必每次都响应。
闭包保存 lastTime(上一次执行时间戳),每次调用判断是否超过间隔:
function throttle(fn, delay) {
let lastTime = 0;
return function (...args) {
const now = Date.now();
if (now - lastTime >= delay) {
fn.apply(this, args);
lastTime = now;
}
};
}更健壮的版本(支持 leading / trailing):
function throttle(fn, delay, options = {}) {
const { leading = true, trailing = false } = options;
let lastTime = 0;
let timer = null;
<p>return function (...args) {
const now = Date.now();
const remaining = delay - (now - lastTime);</p><pre class="brush:php;toolbar:false;">if (leading && !lastTime) {
fn.apply(this, args);
lastTime = now;
} else if (trailing && remaining 0) {
timer = setTimeout(() => {
fn.apply(this, args);
lastTime = Date.now();
timer = null;
}, remaining);
}}; }
关键点:为什么必须用闭包?
- timer、lastTime 等状态不能放在全局,否则多个节流/防抖实例会互相干扰
- 返回的函数需要持续访问并修改这些私有变量,闭包提供了作用域封闭 + 持久引用的能力
- 每次调用
debounce(fn, ms)都生成独立闭包,互不影响
小提醒:注意 this 和参数传递
上面实现用了 fn.apply(this, args),确保原函数的 this 和参数正确。若用箭头函数定义内部函数,this 会丢失绑定,应避免:
// ❌ 错误:箭头函数捕获的是外层 this,不是调用时的 this
return (...args) => { ... };
<p>// ✅ 正确:普通函数,this 指向调用者
return function (...args) { ... };</p>Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










