什么是防抖

函数防抖(debounce):
概念: 延迟要执行的动作,若在延迟的时间内再次触发动作,则取消之前的动作,重新计算延迟时间
举例: 大家都用过无线键盘、鼠标,它们都有一个共同的特点,为了节省待机时长,都会内置防抖功能。当你在多少时间内没有动鼠标键盘时,它们会自动进入休眠状态,当你动了一下鼠标键盘,它们就会立即苏醒。
实现: 使用定时器setTimeout()
应用: 在前端,大部分情况下会在制作搜索功能的时候使用防抖,例如百度搜索(百度的服务器很强大,近几年已经不使用防抖了)

简而言之: 键盘如果在10 分钟内,没有任何操作就会进入休眠状态,当你在9 分钟时动了一下键盘(按了一下),他就会重新计算10 分钟后进入休眠(如果你在10 分钟内一直使用键盘,它就不会休眠)

具体实现

这里使用到了闭包,关于什么是闭包,你可以看我的这篇文章:https://blog.lete114.top/article/JavaScript-Closure.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<div><input type="text" /></div>
<script>
var inp = document.querySelector("input");
inp.onkeyup = debounce(function () {
console.log(this.value);
}, 300);

/**
* 防抖函数(闭包)
* @param callback 事件触发的操作
* @param wait 在多少毫秒内连续触发事件,重新计数
* @returns {Function}
*/
function debounce(callback, wait) {
let timeout = null; // 使用闭包来保存timeout
return function () {
if (timeout) clearTimeout(timeout);
timeout = setTimeout(() => callback.apply(this,arguments), wait);
};
}
</script>

什么是节流

函数节流(throttle):
概念: 规定一个时间段,让函在规定的时间内只能执行一次,避免频繁触发动作
举例: 你有个评论系统,你需要限制用户的提交操作,在规定的时间内容,只能提交 1 次,如用户发了一条评论,在10 秒内如果触发一条或多条新的评论,则提示您评论太快啦!请稍后评论。,只有超过10 秒再次评论才能评论成功,如果没有做节流操作的话,很可能会照成很多次评论(评论攻击),假设有些小人用脚本频繁发生评论,1 分钟内可能评论不止60 条,如果做了防抖处理的话,1 分钟只能评论6 条
实现: 定时器 + 限制标识、定时器 + 时间戳
应用: 当鼠标滚轮滚动的时候,每隔两秒执行一次

具体实现

定时器 + 限制标识

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
27
28
29
30
31
<style>
body {
height: 200vh;
}
</style>
<script>
window.onscroll = throttle(function () {
let scrollTop =
document.body.scrollTop || document.documentElement.scrollTop;
console.log("滚动条位置:" + scrollTop);
}, 2000);

/**
* 防抖节流(闭包)
* @param callback 事件触发的操作
* @param wait 在多少毫秒内连续触发事件,重新计数
* @returns {Function}
*/
function throttle(callback, wait) {
let flag = true; // true 第一次一开始就执行 false 2秒后再执行
return function () {
if (flag) {
flag = false;
setTimeout(() => {
flag = true;
callback.apply(this,arguments);
}, wait);
}
};
}
</script>

定时器 + 时间戳

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
27
28
29
<style>
body {
height: 200vh;
}
</style>
<script>
window.onscroll = throttle(function () {
let scrollTop =
document.body.scrollTop || document.documentElement.scrollTop;
console.log("滚动条位置:" + scrollTop);
}, 2000);

/**
* 防抖节流(闭包)
* @param callback 事件触发的操作
* @param wait 在多少毫秒内连续触发事件,重新计数
* @returns {Function}
*/
function throttle(callback, wait) {
let pre = 0;
return function () {
let now = new Date();
if (now - pre > wait) {
callback.apply(this,arguments);
pre = now;
}
};
}
</script>

总结

函数防抖(debounce): 将多次操作合并为一次操作进行。原理是维护一个计时器,在规定时间后触发函数,但是在规定时间内再次触发的话,就会取消之前的计时器而重新设置计时。只有最后一次操作能被触发

简而言之: 已经触发函数,如果在2s内继续触发函数,则永远都不会触发函数,直到你在2s内不再触发函数,才会触发一次

函数节流(throttle): 规定时间内只触发一次函数。如果在规定时间内多次触发函数,最终只会触发一次函数

简而言之: 已经触发函数,如果在2s内继续触发函数,只会触发一次(2s内不管触发多少次,最终只会触发一次函数)