前言
函数防抖和函数节流是面试题的常客了,所以我们还没有了解的兄弟萌赶紧看起来吧!
概念和例子
函数防抖(debouce)
事件在触发后过n秒再执行回调函数,如果这个事件在n秒内再次被触发,则会重新计时。 这是什么意思呢,就是字面意思,就好比你玩CF里面的加特林,你必须得按住鼠标级几秒钟之后才能开枪,如果你猛点鼠标,这枪管就一直得重新蓄力。函数防抖就类似于此,就是为了防止多次的连续点击。
- 我们举一个普通例子
let btn = document.getElementById('btn') //获取到页面的一个dom按钮
btn.addEventListener('click',a) //给它添加监听事件
function a(){
console.log('提交成功');}
运行结果:
我们可以看到,我们点击多少次,就会打印多少次。这在我们的数据请求过程中是非常不友好的。所以
我们可以用函数防抖也解决这一问题。
2.添加函数防抖
let btn = document.getElementById('btn')
btn.addEventListener('click',debance(a,1000))
function a(){
console.log('提交成功');
}
function debance(fn,delay){ //防抖函数
let timer = null //保存上一次的定时器
return function(){
clearTimeout(timer) //清除定时器
timer = setTimeout(()=>{
fn.apply(this) //因为这里是箭头函数,this指向的是return 的匿名函数,使fn的this指向btn
},delay)
}
}
我们看加了防抖之后的运行结果:
我们可以看到在我们一直点击按钮的时候并不会显示输出,只有当停下来过了一秒后才显示输出。
- 防抖的 实现核心就是利用闭包来保存住上一次的定时器,当在规定单位时间内再次点击时,清除上一次的事件,并重新开始一个新的定时器。
函数节流(throttle)
节流是在一个规定时间内只触发一次函数,如果在这个规定时间内触发多次函数,也只会生效一次 这个就比较好理解了,这就相当于你在打连狙,你不停的点击鼠标开枪,但是枪还是只会有规律的每隔一段时间开一枪,这就是节流的意义了,节约流量嘛。
- 添加节流函数
let btn = document.getElementById('btn')
btn.addEventListener('click',throttle(a,3000))
function a(){
console.log('提交成功');
}
function throttle(fn,delay =1000){
let prex = 0
return function(){
let now = Date.now() //定义一个时间戳
if(now - prex >=delay){ //如果这一次的点击时间减去上一次的点击
fn.apply(this) //因为fn的this指向window,所以要用apply修改this指向btn
prex = now //并把这一次的时间赋值给prex
}
}
}
我们看输出结果:
我们可以看到,当我们把规定时间内设置成三秒后,我们不断的点击按钮,按钮也只会在第一次点击输出后每隔三秒输出一次。
- 节流的实现核心也是利用闭包来保存上一次点击的时间,如果下一次的点击时间与上一次的点击时间小于规定时间,则不会触发输出函数
总结
-
函数防抖和节流都是为了防止在一定时间内频繁点击。
-
防抖是在一定时间内只执行一次,节流是间隔单位时间持续执行。
应用场景
防抖和节流的实现原理不同,这就导致了它们的运用场景也不相同
- debouce
- 用户在搜索时,不断输入值或者发起接口请求时,用防抖也节约请求资源
- throttle
- 鼠标不断点击触发,mousedown(单位时间内只触发一次)