節流函式怎麼寫?

Z不懂發表於2018-04-17

平時我們在開發中,會經常使用到resize和movesemove事件,這些事件會在短時間內頻繁的執行事件繫結程式,我們知道頻繁的操作DOM會帶來很大的效能消耗,頁面會促發迴流和重繪。有時候頁面會出現卡頓,在IE瀏覽器下可能直接崩潰。這時候節流函式就發揮作用了。

什麼是函式節流?

簡單講就是讓一個函式無法在短時間內連續呼叫,只有當上一次函式執行後過了規定的時間間隔,才能進行下一次該函式的呼叫。或者說你在操作的時候不會馬上執行該函式,而是等你不操作的時候才會執行。

函式截流的原理

通過使用定時器,在操作的時候讓函式延時執行,如果在這個時間內還在操作,則清除原來的定時器,再建立一個新的定時器執行

方式一:

最簡單的操作方式,在操作的的時候清除上次的定時器,不操作的事後在執行callBack回撥

//封裝
/**
*  @  { Function} callBack    回撥程式    
*/
function throttleFn(callBack){
    clearTimeout(method.timer);
    method.timer=setTimeout(()=>{
        method()
    },100)
}

//呼叫
window.onresize=function(){
    throttleFn(callBack)
}

複製程式碼

方式二

優勢在於把延遲時間當做變數,而且使用閉包保護私有變數,缺點就是雖然使用apply把呼叫throttleFn時的this上下文傳給執行函式,但畢竟不夠靈活

//封裝
/**
*  @  { Function} callBack    回撥程式    
*  @  { Number } delay  延時時間
*  return  { Function }
*/
function thorttleFn(callBack,delay){
    var timer=null;
    return function(){
        var context=this;
        clearTimeout(timer);
        timer=setTimeout(()=>{
            callBack.apply(context,arguments)
        },delay)
    }
}

//呼叫
window.onresize=thorttleFn(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)

複製程式碼

相關文章