js中的防抖和节流
曾经看过一个经典的比喻:
想象每天上班大厦底下的电梯。假设电梯有两种运转方法:
debounce 和 throttle,超时设定为15秒,不考虑容量限制。
电梯第一个人进来后,15秒后准时运送一次,这种情况叫做节流;
而当电梯第一个人进来后,等待15秒的过程中还陆续有人进入电梯,那么重新计时,直到15秒后开始运送,这种情况叫做防抖。
防抖 debounce
防抖,就是指在指定时间内只能触发一次事件,如果触发事件后在 n 秒内又触发了事件,则会重新计算函数延执行时间。
使用场景:页面大小调整,鼠标的移入移出等情况,这种在短时间内频繁触发的时候需要用到防抖。
代码实现防抖函数
const debounce = (handle, wait, immediate) => {
// debounce是一个函数,并且需要传入一个函数handle
// 传入函数后,我们要传入一个防抖时间wait
// 需要判断是否立即执行immediate
// 首先进行参数判断
if (typeof handle !== 'function')
throw new Error('Handle must be function!');
// 默认wait为1s
if (typeof handle === 'undefined') wait = 1000;
// 如果只传入 handle 和 immediate
if (typeof wait === 'boolean') {
immediate = wait;
wait = 1000;
}
if (typeof immediate !== 'boolean') immediate = false;
let timer = null;
return function proxy(...args) {
let self = this,
init = immediate && !timer;
clearTimeout(timer);
timer = setTimeout(() => {
timer = null;
!immediate ? handle.apply(self, args) : null;
}, wait);
// 如果立即执行
init ? handle.apply(self, args) : null;
};
};
函数节流 throttle
函数节流,就是指触发事件后,在n秒内函数只能执行一次,如果触发事件后在n秒内又触发了事件,则会再次执行该事件。顾名思义,就是像水管流水一样,有频率的执行。
const throttle = (handle, wait, immediate) => {
if (typeof handle !== 'function')
throw new Error('handle must be an function');
if (typeof wait === 'undefined') wait = 1000;
//如果只传入 handle 和 immediate
if (typeof wait === 'boolean') {
immediate = wait;
wait = 1000;
}
//immediate默认为flase
if (typeof immediate !== 'boolean') immediate = false;
//定义变量记录上一次执行的时间
let previous = null
let timer = null
return function proxy(...args){
let now = new Date()
let self = this
if(!immediate) previous=now
let interval = wait-(now-previous)
if(interval<0){
clearTimeout(timer)
timer = null
handle.apply(self,args)
previous = new Date()
}else if(!timer){
timer = setTimeout(()=>{
clearTimeout(timer)
timer = null
handle.apply(self,args)
previous = new Date()
},interval)
}
}
};
两者的相同点和不同点
相同点
- 都是通过 clearTimeout 和 setTimeout 实现
- 都是通过降低执行频率来达到节省资源的目的
不同点
- 函数防抖,在一段连续操作结束后,处理回调,利用clearTimeout和 setTimeout实现。函数节流,在一段连续操作中,每一段时间只执行一次,频率较高的事件中使用来提高性能
- 函数防抖关注一定时间连续触发的事件,只在最后执行一次,而函数节流一段时间内只执行一次