函数的防抖和节流,学前端也不少时间了,这两个词还是第一次遇到,给自己科普一波。

函数防抖debounce:指定时间间隔内只会执行一个任务。
举个例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE html>
<html>
<head>
<title>demo</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<input @keyup="write" />
</div>
</body>
<script type="text/javascript">
new Vue({
el: "#app",
data: {},
methods: {
write: function() {
console.log(123)
}
}
})
</script>
</html>

当我们在输入框中输入内容(即键盘触发一次keyup事件)都会打印一次123,如图
高频率触发

防抖就是要控制这个频率,比如用500ms作为一次频率间隔

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
<!DOCTYPE html>
<html>
<head>
<title>demo</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<input @keyup="write" />
</div>
</body>
<script type="text/javascript">
new Vue({
el: "#app",
data: {
timeout: null
},
methods: {
write: function() {
if(this.timeout) {
clearTimeout(this.timeout)
}
this.timeout = setTimeout(()=>console.log(123),500)
}
}

</script>
</html>

效果如下:
防抖
具体理解一下这段代码:
clearTimeout是用来清除定时器的,上述代码中,当我们第一次触发keyup事件的时候,timeout(定时器返回的id)是null,所以不会对timeout做清除操作,接下去第一次触发定时器操作,定时时间是500ms,假设此时timeout被赋值为1,如果在这个500ms的时间内,再次触发keyup操作时候,会清除timeout,也就是说,第一个500ms内触发的那次操作将被取消,以此类推,最终的触发时间按照第一个超过500ms还没继续触发的操作为准。
函数节流
接下来看节流,话说这个词语很抽象,其实就是指连续触发事件但是在 一段时间内只执行一次函数。节流会稀释函数的执行频率,节流有两种实现方式,一种是利用时间戳,代码如下:

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
<!DOCTYPE html>
<html>
<head>
<title>demo</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<input @keyup="write" />
</div>
</body>
<script type="text/javascript">
new Vue({
el: "#app",
data: {
previous: 0 // 记录当前时间
},
methods: {
write: function() {
var now = +new Date();
if((now - this.previous)>5000000) {
console.log(123)
this.previous = now
}
}
}
})
</script>
</html>

上面的代码可以看出来,函数只能在_5000000ms_中执行一次

另外一种是还是使用定时器(😂乍一看和防抖没啥差别,所以还是需要理解其中的奥义)
代码如下:

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
<!DOCTYPE html>
<html>
<head>
<title>demo</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<input @keyup="write" />
</div>
</body>
<script type="text/javascript">
new Vue({
el: "#app",
data: {
timeout: null
},
methods: {
write: function() {
// this.timeout = null i
if(!this.timeout) {
this.timeout = setTimeout(()=>{
this.timeout = null;
console.log(123);
}, 1000)
}
}
}
})
</script>
</html>

理解一下防抖的函数:
上面代码中,定时器值timeout初始化值为空,如果定时器为空则通过setTimeout()延时,并且timeout赋值为当前触发定时器的返回id,并在>=1000ms之后将定时器再次置为空,才能触发下一次的操作。第一次触发keyup事件的时候因为timeout = null所以会触发定时器,假设触发之后timeout = 1,然后在1000ms内被再次触发了事件,此时因为timeout = 1了,所以这个1000ms内触发的事件都不会被操作,直到1000ms之后,timeout重新被赋值为null,方可进行再一次的keyup事件触发。

引用别人博客中的一段话
函数节流是指一定时间内js方法只跑一次。比如人的眨眼睛,就是一定时间内眨一次。这是函数节流最形象的解释。
函数防抖是指频繁触发的情况下,只有足够的空闲时间,才执行代码一次。比如生活中的坐公交,就是一定时间内,如果有人陆续刷卡上车,司机就不会开车。只有别人没刷卡了,司机才开车。

防抖一般应用于的场景:输入查询 当用户停止输入一段时间之后 就触发查询
节流一般像不停的点击触发,就可以用节流,稀释了操作的次数。

虽然自己整理以及操作了一遍,但是对这两个概念还只是自己的一些理解,若有偏差,望指正~