防抖和节流函数怎么写?

3,999 阅读2分钟

平时我们在开发中,会经常使用到resize和movesemove事件,这些事件会在短时间内频繁的执行事件绑定程序,我们知道频繁的操作DOM会带来很大的性能消耗,页面会促发回流和重绘。有时候页面会出现卡顿,在IE浏览器下可能直接崩溃。这时候节流函数就发挥作用了。

什么是防抖?

简单讲就是让一个函数无法在短时间内连续调用,只有当上一次函数执行后过了规定的时间间隔,才能进行下一次该函数的调用。或者说你在操作的时候不会马上执行该函数,而是等你不操作的时候才会执行。

通过使用定时器,在操作的时候让函数延时执行,如果在这个时间内还在操作,则清除原来的定时器,再创建一个新的定时器执行

/**
*  @  { Function} callBack    回调程序    
*  @  { Number } delay  延时时间
*  return  { Function }
*/
function debounce(callBack,delay=200){
    var timer=null;
    return function(){
        var context=this;
        clearTimeout(timer);
        timer=setTimeout(()=>{
            callBack.apply(context,arguments)
        },delay)
    }
}

//调用
window.onresize=debounce(myFunc,300)

什么是节流

其实防抖函数的出发点,就是让一个函数不要执行得太频繁,减少一些过快的调用来节流,减少性能消耗。当你在操作resize和mousemove事件的时候,浏览器其实是有设置一个时间间隔,这个时间是多少我们不清楚,而且他们没有提供参数去设置,所以需要我们在他们的基础上再去做一些改变。真正的节流应该是在可接受的范围内尽量延长这个调用时间,也就是我们自己控制这个执行频率,让函数减少调用以达到减少计算、提升性能的目的。假如原来是16ms执行一次,我们如果发现resize时每50ms一次也可以接受,那肯定用50ms做时间间隔好一点。

/**
*  @  { Function} callBack 回调程序    
*  @  { Number } delay  延时时间
*  @  { Number }  intervalTime  间隔时间
*  return  { Function }
*/
function thorttleFn(callBack,delay,intervalTime){
    var timer=null;  // 定时器变量
    var time=0;  // 时间变量
    return function(){
        var context=this;
        var curTime=new Date();  // 当前执行的时间
        clearTimeout(timer);  //  清除上次的定时器
        
        if(!time){
            time=curTime;
        }
        // 当前执行时间距离上次执行的时间是否大于等于间隔时间
        if(curTime - time >= intervalTime){
            time=curTime;
            callBack.apply(context,arguments)
        }else{
            timer=setTimeout(()=>{
                callBack.apply(context,arguments)
            },delay)
        }
    }
}

//调用
window.onresize=thorttleFn(myFunc,50,300)