前言
防抖和节流都是用于减少触发频率,减少js对dom的操作,提高性能,用于频繁触发的事件mousedown、mousemove、keyup、keydown等。
一、 什么是防抖
防抖是指事件触发后在延迟一定的时间再去执行,若在延迟时间内再次触发则重新计算延迟时间;打比方:
大巴车总要等到最后一位乘客上车一分钟后再出发,这时A乘客上车了,大巴车开始倒计时一分钟,但倒计时未结束时,B乘客上车了,这是大巴车需要重新进行一分钟的倒计时,C乘客D乘客上车以此类推,等到某位乘客上车后,公交车倒计时一分钟,倒计时结束没有乘客继续上车,这时大巴车将出发。(乘客上车就是事件触发,大巴车固定等最后一位乘客上车一分钟后出发就是设置的时间,大巴车出发就是执行)
二、什么是节流
节流是指固定时间内多次触发也只执行一次,流程是先触发事件执行任务,然后设置间隔时间,在间隔事件内触发事件将不会执行,间隔时间结束后触发事件才会执行,接着又设置间隔时间,依次类推,打比方:
游戏中的一些大招是不是都有冷却时间,冷却时间进度条没满时,无论你怎么点是不是都没用,你每一次去点击大招都是触发事件,冷却时间进度条就是设置的间隔时间,进度条满了之后你点击大招就会释放大招,那就是执行。
三、防抖和节流的区别
防抖和节流的区别是,防抖是触发然后延迟执行(你不能一直点,只有结束点击才会有用,就是你一直点和点一次效果是一样的都是要在点完后过一会执行,反而一直点只会更晚执行),节流是通过时间间隔减少触发执行(间隔时间内点击无效,间隔事件后点击才会有效,就是你连着点击20下,可能只执行2次,别人隔一段时间去点,点两2下就执行2次)
总结一点: 就是防抖和你每一次点击都是有关的,因为每点一次点击都会重新计算延迟时间,而节流主要是和设置的间隔时间有关,在间隔时间内每一次点击都无效就是点没点都一样。
四、手动实现防抖节流
1.防抖(debounce)
//防抖函数
function debounce(fun,delay){
//定时器变量写在返回函数之前,是利用闭包原理,全局形成一个定时器,这样每次点击都是操作同一个定时器
//若是写在返回函数里面,相当于每次点击都是创建一个新的定时器,这样每个定时器互不干涉,就无法起到重新计时的作用,我们必须在同一个计时器上操作
let timer=null;
//高阶函数,函数里返回函数,直接写定义监听函数时fun将会立即执行fun函数
return function(){
//确保this指向不变
let thisObj = this;
let args = arguments;
clearTimeout(timer)
timer = setTimeout(()=>{
fun.call(thisObj,...args)
},delay)
}
}
2.节流(throttling)
写法一
触发后执行,然后设置间隔时间
function throttling(fun,delay){
let timer = true;
return function(){
let thisObj = this;
let args = arguments;
if(timer){
fun.call(thisObj,...args);
timer = false;
setTimeout(()=>{
timer = true;
},delay)
}
}
}
写法二
触发后设置延时执行
function throttling(fun,delay){
let timer = null;
return function(){
let thisObj = this;
let args = arguments;
if(timer){
return;
}
timer = setTimeout(()=>{
fun.call(thisObj,...args);
timer = null;
},delay)
}
}
写法三
使用date时间对象计算时间差来实现
function throttling(fun,delay){
let preTime = 0;
return function(){
let thisObj = this;
let args = arguments;
let nowTime = new Date()
if(nowTime - preTime > delay){
fun.apply(thisObj,args);
preTime = nowTime
}
}
}