1. 什么是防抖
简单理解,防抖就是当用户频繁触发某一个事件的时候,我们不总是立马发送请求,而是延长一段时间发送请求,举个栗子:
现在我们需要实现一个搜索推荐功能,当用户在输入框输入文字的时候,我们不对每次用户输入立马发送请求,而是等待用户输入停止后过一段时间才向服务器发送请求
假设现在我们有一个需求,实现搜索推荐,在用户停止输入3秒后才发送请求给服务器(这意味着如果用户停止输入3秒以内之后继续输入,则我们不做请求发送)
2. 实现简单的防抖
为了实现这个需求,我们需要实现防抖,延后我们的函数的执行,我们知道setTimeout函数可以做到这一点,例如我们可以使用setTimeout(function, 3000)在3秒后执行function. 但注意,如果我们直接这么使用,并不能实现防抖。
注意到需求: 如果用户停止输入3秒以内之后继续输入,则我们不做请求发送, 所以我们需要在用户继续输入的时候重置我们的timer,重新计时。既然我们需要重置timer,那么必然需要先定义timer,并且在每次触发函数的时候可以重置timer,我们自然地想到了使用一个包装函数,然后将真正要执行的函数写成一个闭包
0. 模拟用户暂停然后继续输入
1. 示例代码
const debounce = (mainFunction, delay) => {
// store the timer id
let timer;
// that is a closure
return function (...args) {
// call this first time, it simply does nothing here
clearTimeout(timer);
timer = setTimeout(() => {
mainFunction(...args);
}, delay)
}
}
function searchData() {
console.log("searchData executed");
}
const debouncedSearchData = debounce(searchData, 3000);
debouncedSearchData();
1. 防抖函数程序调用时,JS内存图
为什么上述的写法,可以形成一个闭包,做到调用防抖函数的时候可以做到clearTimeout(timer)从而实现我们的需求,接下来的内存图解析基于ES3:
当debounce执行上下文和debouncedSearchData上下文执行完被弹出的时候:
从GC的角度,AO1仍然是可达的,因此不会被回收,从而保留了debouncedSearchData的外部环境,实现了闭包,从而可以使得我们实现在用户停止输入2秒内又继续输入(我们可以清除timer)