防抖与节流
大约 2 分钟
防抖与节流
防抖与节流是我们在开发中经常用到的工具函数,它们的作用是降低事件的触发频率,从而提高性能。
防抖函数
防抖函数的作用是在一定时间内,事件被触发 n 次,只会执行一次回调函数。如果在一定时间内事件再次被触发,则会重新计算执行时间。
function debounce(callback,delay){
//设置定时器,用来表示事件是否触发过
let timer = null
return function(){
//保存 this 上下文与参数
let that = this
let args = arguments
//如果timer存在,表示重复触发了事件,清空已经存在的定时器(即取消即将执行的回调函数)
if(timer){
clearTimeout(timer)
timer = null
}
//重新设置定时器,在到达给定的延迟后触发一次回调函数执行
timer = setTimeout(()=>{
callback && callback.apply(that,args)
},delay)
}
}
防抖函数经常用于输入框搜索事件、窗口大小变化事件等。
节流函数
节流函数的作用是在一定时间内只执行一次回调函数,如果在这个时间内再次被触发,不会执行,直到下一个时间段。
一般节流函数
function throttle(callback,delay){
//设置定时器,表示事件是否触发
let timer = null
//记录开始时间,表示事件触发的时间,后续再次触发会更新这个时间
let start = Date.now()
return function(){
//保存 this 上下文与参数
let that = this
let args = arguments
//如果timer存在,表示重复触发了事件,清空已经存在的定时器(即取消即将执行的回调函数)
if(timer){
clearTimeout(timer)
timer = null
}
//当重复触发事件后,计算给定的时间间隔与事件触发时间之间的的差值
let remaining = delay - (Date.now() - start)
if(remaining <= 0){
//时间差值小于等于0 ,则说明已经到达给定的时间间隔,可以触发回调函数执行
callback && callback.apply(that,args)
start = Date.now()
}else{
//如果时间差值大于0,则说明还没有到达下一个时间间隔,将回调函数放入定时器中
//等待到达给定的时间间隔后执行回调
setTimeout(()=>{
callback && callback.apply(that,args)
},delay)
}
}
}
一般节流函数经常用于滚动事件、表单按钮提交事件等。
raf节流函数
function rafThrottle(callback,delay){
//设置触发锁
let lock = false
return function(){
//如果触发锁为true,说明事件已经触发过,直接返回
if(lock){
return
}
//如果触发锁为false,说明事件没有触发,此时可以触发回调执行,将触发锁设置为true
lock = true
//保存 this 上下文与参数
let that = this
let args = arguments
//利用 requestAnimationFrame 函数来触发回调执行
window.requestAnimationFrame(()=>{
callback && callback.apply(that,args)
lock = false
})
}
}
由 requestAnimationFrame 实现的节流函数适合用于控制执行与渲染相关的高频事件。