前言
前面写过关于JavaScript
的this
指向的基础文章,链接:juejin.cn/post/751796...
今天我们继续来讲讲闭包的应用场景之一:防抖和节流
防抖 debounce
场景举例:
有一个搜索框,用户每打一个字就发请求去服务器查结果。这样效率太低了,而且对服务器压力大。
你希望的是:等用户输入完停顿一下再发请求,比如停顿500毫秒后再发。
那要如何实现?
我们可以写个函数,在每次按键的时候先取消上一次还没执行的请求,设定一个新的定时器。
这时候就需要一个变量来保存"上一次的定时器",而这个变量不能轻易被外部干扰或重置 ------ 闭包正好可以做到这一点。
js
function debounce(func, delay) {
let timer; // 这个变量会被闭包保留住
return function(...args) {
clearTimeout(timer); // 清除之前的定时器
timer = setTimeout(() => {
func.apply(this, args); // 执行目标函数
}, delay);
};
}
最后一次按键之后
delay
时间执行,前面的都会清除定时器。
闭包的作用是:让timer
变量一直存在,不会被销毁,这样每次都能判断是否需要清除旧的定时器。
节流 throttle
场景举例:
想监听用户的滚动事件,当页面滚动到底部时加载更多内容。但滚动事件非常频繁,可能一秒触发几十次,没必要每次都处理。
我们希望的是:每隔一定时间只执行一次处理逻辑,比如每1000毫秒最多执行一次。
怎么实现?
可以用一个变量记录上次执行的时间,或者记录是否正在"冷却中"。如果还在冷却期,就不执行新的操作。
同样地,这个变量也需要一直保留下来,不能每次调用都重新初始化 ------ 闭包再次派上用场!
js
function throttle(func, delay) {
let lastTime = 0; // 记录上一次执行的时间戳
return function(...args) {
const now = Date.now();
if (now - lastTime >= delay) {
func.apply(this, args); // 执行函数
lastTime = now; // 更新时间
}
};
}
闭包的作用是:让
lastTime
一直保留在内存里,这样每次调用函数都能知道上次执行是什么时候。
总结
- 闭包就像一个小房间,里面的东西不会随便被别人动。
- 在防抖和节流中,我们用闭包来保存一些"状态"(如定时器、时间戳),这些状态不会被外部干扰,也不会随着函数调用结束就被清空。
- 所以闭包成了实现防抖和节流的完美工具!
如果还觉得有点抽象,可以想象成:
防抖就是:等你做完一件事之后,过一会儿才执行操作。如果你一直做,那就一直不执行。
就像你打字的时候,系统不是你每按一个键就搜索,而是等你停下来之后才开始搜索。
用户输入"hello",每敲一个字母就去服务器查结果,效率很低。加上防抖后,用户输入完
hello
后停顿500毫秒,才去搜索一次。防抖的核心思想是: "别急着执行,等你停了再说。"
节流就是:控制某个动作的执行频率。比如你有一个按钮,每次点击都会播放音乐,但如果用户疯狂点100次,你不希望真的播放100次音乐。
你可以加个"节流器",规定:每5秒钟只能播放一次音乐。