由于在面试的时候被问到防抖和节流,然后不太会,就学习记录下。之前有听说过防抖和节流,但是在实际的项目中没有用到过(还是项目做少了hh),只知道它们是用来改变事件函数的执行频率的,但是具体的还是不了解,所以要加深下印象。
防抖和节流简介
在前端开发的过程中,我们经常会需要绑定一些持续触发的事件,如 resize、scroll、mousemove 等等,但有些时候我们并不希望在事件持续触发的过程中那么频繁地去执行函数。通常这种情况下我们怎么去解决的呢?一般来讲,防抖和节流是比较好的解决方案。防抖和节流也是有区别的,防抖动是将多次执行变为最后一次执行,节流是将多次执行变成每隔一段时间执行。
- 防抖(debounce):触发高频事件后 n 秒内函数只会执行一次,如果 n 秒内高频事件再次被触发,则重新计算时间。
- 节流(thorttle):高频事件触发,但在 n 秒内只会执行一次,所以节流会稀释函数的执行频率。
就好像在百度搜索时,每次输入之后都有联想词弹出,这个控制联想词的方法就不可能是输入框内容一改变就触发的,他一定是当你结束输入一段时间之后才会触发,这个是防抖。就好像你在淘宝抢购某一件限量热卖商品时,你不断点刷新点购买,可是总有一段时间你点上是没有效果,这里就用到了节流,就是怕点的太快导致系统出现 bug 。
防抖的实现
防抖有立即执行和非立即执行两种版本,区别在于立即执行版本是触发之后立即执行,再次触发的时候会更新计时器,直到不再触发,计时器计时结束,才能再次执行函数。非立即执行版本则是将事件触发放在计时器函数内部,计时结束之后才会执行。
非立即执行版本:
function debounce(event,time){
let timer
return function(...args){
clearTimeout(timer)
timer = setTimeout(()=>event.apply(this,args),time)
}
}
立即执行版本:
function debounce(event,time){
let timer
let flag = true
return function(...args){
clearTimeout(timer)
if(flag){
event.apply(this,args)
flag = false
}
timer = setTimeout(()=>flag=true,time)
}
}
节流的实现
节流有时间戳和计时器两种版本。
时间戳版本:
function thorttle(event,time){
let pre = 0
return function(...args){
let now = Date()
if(now-pre>=time){
event.apply(this,args)
pre = Date()
}
}
}
计时器版本:
function throttle(event,time){
let timer = null
return function(...args){
if(!timer){
setTimeout(()=>{
timer = null
event.apply(this,args)
},time)
}
}
}