1. 程式人生 > 其它 >手寫節流函式

手寫節流函式

節流原理

如果持續的觸發事件,每隔一段時間,只執行一次事件

應用場景

  1. DOM元素的拖拽功能實現
  2. 射擊遊戲
  3. 計算滑鼠移動的距離
  4. 監聽scroll滾動事件

underscore中的防抖函式_.throttle

contant.onmousemove = _.throttle(doSomeThing, 2000, {
    leading: false, //禁用首次執行,即禁用第一次呼叫事件函式立即執行
    trailing: false //禁用最後一次執行
    //二者不能都為false,將會產生bug
});

防抖函式實現原理:時間戳 + 定時器

1. 時間戳實現
第一次觸發,最後一次不觸發 { leading:true, training: false }

function throttle(func, wait){
    let context, args;
    //之前的時間戳
    let old = 0;
    return function(){
        context = this;
        args = arguments;
        //獲取當前時間戳
        let now = new Date().valueOf();
        if(now-old > wait){
            // 立即執行
            func.apply(context,args);
            old = now;
        }
    }
}

2. 定時器實現
第一次不觸發,最後一次觸發{ leading:false, training: true }

function throttle(func, wait){
    let context, args, timeout;
    return function(){
        context = this;
        args = arguments;
        if(!timeout){
            timeout = setTimeout(()=>{
                timeout = null;
                func.apply(context,args);
            },wait)
        }
    }
}

3.時間戳+定時器

function throttle(func, wait, options){
    let context, args, timeout;
    let old = 0; //時間戳
    if(!options) options = {};

    let later = function() {
        old = new Date().valueOf();
        timeout = null;
        func.apply(context,args);
    }
    return function(){
        context = this;
        args = arguments;
        let now = new Date().valueOf();
        if(options.leading === false){
            old = now;
        }
        if(now-old > wait){
            //第一次直接執行
            if(timeout){
                clearTimeout(timeout);
                timeout = null;
            }
            func.apply(context, args);
            old = now;
        }else if(!timeout && options.trailing !== false){
            //最後一次會執行
            timeout = setTimeout(later, wait);
        }
    }
}