# 防抖函数&节流函数
节流函数和防抖函数是 JS 比较重要的概念,应用好了可以提高很大的性能,在面试中也是很高频的一个考点。下面一起来看看这两种方法是如何使用的:
# 防抖函数(debounce):
# 概念:
在事件被触发 n 秒后再执行回调,如果在这 n 秒内又被触发,则重新计时。
# 生活中的栗子:
如果有人进电梯(触发事件),那电梯将在 10 秒钟后出发(执行事件),这时如果又有人进电梯了(在 10 秒内再次触发该事件),我们又得等 10 秒再出发(重新计时)。
# 代码栗子:
/**
* @description: 防抖函数:函数被触发 n 秒后再执行回调,如果在这 n 秒内又被触发,则重新计时
* @param {Function} fn 要执行的函数
* @param {Number} wait wait毫秒后执行回调
* @param {*} ...arr 传递给fn的参数
*/
function debounce(fn, wait, ...arr) {
let timer = null;
return () => {
if (timer) {
// 如果有一个函数在等待执行 清除定时器 下面重新计时
clearTimeout(timer);
timer = null; // 清空timer 下次重启定时器
}
// 设定时器/重置定时器
timer = setTimeout(() => {
fn(...arr); // wait时间后 执行回调 期间再触发debounce 需要重新等待
}, wait);
};
}
// 要防抖的函数
let actionFn = function(a, b) {
console.log('回调', a, b);
};
setInterval(debounce(actionFn, 500, 'actionFn参数1', '参数2'), 1000); // 第一次在1500ms后触发,之后每1000ms触发一次
setInterval(debounce(actionFn, 2000), 1000); // 还没执行就一直重复触发,不会执行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
可以这样理解
函数触发停止一段时间后(期间不能再触发 debounce,否则将重新计时),再执行回调函数
# 机制:
防抖函数主要利用定时器的延迟执行特性,根据是否有定时器在等待执行:
- 触发了一个事件后:如果有一个定时任务待执行,就清除定时器,重新计时。
- 如果没有任务待执行,就定时执行这个事件。
# 应用场景:
- 表单的连续点击,防止重复提交。比如重复发送一篇文章。
- 类百度的搜索,连续输入等输入停止后再搜索。
- 一直拖动浏览器窗口,只想触发一次事件等。
# 节流函数(throttle):
# 概念:
规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行(单位时间内有事件被多次触发则,只生效一次)。
# 生活中的栗子:
漏水的自来水水龙头,尽管水龙头里面有很多水(一直在触发事件),但还是一滴一滴的往下滴(单位事件内只生效一次)。
# 代码栗子:
/**
* @description: 节流函数:规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行
* @param {Function} fn 要执行的函数
* @param {Number} gapTime 单位时间
* @param {*} ...arr 传递给fn的参数
*/
function throttle(fn, gapTime, ...arr) {
let last = 0; // 上次执行时间 第一次马上执行
return () => {
let nowTime = Date.now(); // 当前时间
// 当前时间-上次执行的时间是否超过间隔时间 就执行回调
if (nowTime - last > gapTime) {
fn(...arr); // ...arr为fn的参数
last = nowTime; // 重置上次执行时间为当前时间 方便下次执行
}
};
}
let actionFn = (a, b) => {
console.log('回调', a, b); // 要执行的函数
};
setInterval(throttle(actionFn, 1000, 'actionFn参数1', '参数2'), 10);
// 每隔10毫秒都会触发一次throttle,每隔一秒触发一次actionFn回调(1秒内再次触发被丢弃)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 机制:
节流函数根据时间差是否超过给定时间(gapTime)来决定是否触发回调。
# 应用场景:
- 自动保存草稿功能,当用户在输入的时候(一直触发事件),单位时间内只保存一次草稿。
- 游戏中的刷新率
# 作用和本质:
防抖函数和节流函数主要解决的问题是:防止函数”短时间“的重复执行。
它们本质上是:在时间轴上控制函数的执行次数。
# 应用实例,需要加个括号:
因为返回debounce
和throttle
返回的是一个函数,所以如果不是自动执行的事件监听回调,我们应该再后面加个()
,执行返回的闭包函数。
document.onclick = () => {
// throttle(actionFn, 1000) 这样不会执行 只返回了一个闭包函数
throttle(actionFn, 1000, '执行函数参数1', '执行函数参数2')(); // 执行闭包函数
};
1
2
3
4
2
3
4