防抖节流是前端性能优化的一部分了,在一些场景中我们需要使用他们来帮助我们减少不必要的消耗,尤其是对一些监听事件的不必要消耗的优化。

为什么要进行优化?

我们以监听滚动事件来进行举例

1
2
3
window.addEventListener('scroll',()=>{
console.log('test')
})
在这里插入图片描述
在这里插入图片描述

我们可以看到我们这个监听事件的执行频率很高,只要我们划一小部分,触发很多次事件,当我们的时间如果执行的很慢的话很可能页面就会卡死,而且这么高的执行频率我们也不是必要的,很多性能都被浪费掉了,因此对其进行优化,优化的方法就有防抖和节流。

什么是防抖和节流?

防抖:

在某个事件触发n秒后执行,如果在事件触发的n秒内又再次触发,则以新的时间为基准

我们可以使用闭包来实现防抖,使用闭包可以实现对函数的复用,也可以避免对全局作用域的污染,这边要注意我们这边在定时器里使用了箭头函数是为了保留返回的闭包的this指向,因为最后事件是指向调用这个闭包的对象的,而不是指向调用用产生闭包的foo函数的对象。(可能有点绕口)

1
2
3
4
5
6
7
8
9
10
11
12
13
function foo(event,time){
let timer=null
return function(...args){
clearTimeout(timer)
timer=setTimeout(()=>{
event.apply(this,args)
},time)
}
}
function show(){
console.log('111')
}
window.addEventListener('scroll',foo(show,1000))

这个意思就是我们触发了事件都会清空之前的定时器,重新开始计时,这样保证了不管触发在上一次计时范围内或者外都清空计时器并重新计时。

节流:

上面防抖如果我们一直都在触发这个事件,持续出发了很久,但是他也只会执行最后一次,这很显然是不好的,所以我们就有了节流,节流就是不管事件触发的频率有多大,都会在固定的时间间隔内执行一次。
有两种方法可以实现节流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//使用时间戳
function throttle(e,time){
let pre_time=0
return function(...args){
if(Date.now()-pre_time>time){ //超过间隔则执行
pre_time=Date.now()
e.apply(this,args)
}
}
}
//使用定时器
function throttle(e,time){
let timer=null;
return funciton(...args){
if(!timer){
timer=setTimeout(()=>{
timer=null
e.apply(this,args)
},time)
}
}
}