闭包通过让内层函数持续引用外层变量(如timer、this缓存、args、lastexec),使其不被垃圾回收,从而保存执行上下文;防抖/节流中借此确保定时器回调能正确恢复原始this和参数,并隔离不同实例的状态。

闭包保存函数执行上下文,关键在于让内层函数持续引用外层函数作用域中的变量(比如 timer、oldTime 或 this 的缓存值),使这些变量不会随外层函数执行结束而被垃圾回收。
为什么需要保存上下文
事件回调(如 onscroll、oninput)触发时,this 指向绑定的 DOM 元素或全局对象,而定时器回调(setTimeout)里 this 默认是 window 或 undefined(严格模式)。若不保存,业务函数执行时会丢失原始调用对象和参数。
闭包如何保存 this 和参数
在防抖/节流函数工厂中,通过以下方式固定上下文:
- 在外层函数中用
const _this = this或const context = this缓存当前 this - 用
const args = arguments或const args = [...arguments]保存调用时的实参 - 在
setTimeout或时间戳比对后的执行阶段,用func.apply(_this, args)或func.call(_this, ...args)恢复原始上下文和参数
典型闭包结构示例(防抖)
下面代码中,timer、_this、args 都被返回的匿名函数“记住”,形成闭包:
let timer;
return function() {
const _this = this;
const args = arguments;
clearTimeout(timer);
timer = setTimeout(() => {
func.apply(_this, args);
}, delay);
};
}
节流中闭包保存时间戳的原理
时间戳版节流依赖闭包维持 lastExec 变量:
-
let lastExec = 0定义在外层,只初始化一次 - 每次触发时,内层函数读取并更新
lastExec,该变量因被闭包持有而长期存在 - 不同调用实例(如多个输入框分别绑定)互不影响,因为每个
throttle(...)调用都生成独立闭包作用域











