javascript之函數防抖與節流

  平時咱們本身在開發過程當中可能須要監聽窗口的大小(resize等)來調節樣式,或者是根據鼠標移動(mousemove等)來執行相應的方法,以及鍵盤按鍵(keyup等)事件。可是這裏會產生一個問題——頻繁改變窗口大小和移動鼠標會致使前端頁面被頻繁渲染,有時候可能致使頁面崩潰。頁面渲染過程當中也就是dom被操做的過程,而dom操做越頻繁,對前端的性能影響就越大,前端性能也越差,因此大神們就總結除了函數防抖和節流這兩種解決頁面被過渡渲染致使性能低下的問題。 因此在此記錄下以供未來複習,同時也可以經過這些文章來了解到本身哪些時間段學習過什麼內容。前端

一、函數防抖

原理:函數執行過一次後,在等待時間段內不能再次執行。 在等待時間內觸發此函數,則從新計算等待時間。

代碼實現java

/*
    *fn:要防抖的函數
    *wait:要等待的時間
    *immediate:是否馬上執行fn函數
    */
    function debounce(fn,wait,immediate){
        let timer=null; 
        let _debounce=function(){
            //判判定時器是否存在,存在即刪除定時器
            timer&&clearTimeOut(timer);
            //是否馬上執行
            if(immediate){
                //定時器不存在時,纔回去執行函數
                !timer&&fn.apply(this,...arruments)
                timer=setTimeOut(()={
                    timer=null;
                    //過了await時間後,fn才能夠被再次執行
                },await)
            }else{
                timer=setTimeOut(()=>{
                    //過了await時間後,再次設置的定時器纔不會被清除
                    timer=null;
                    fn.apply(this,...arguments);
                    //arguments爲調用fn函數傳入的參數
                },await)
            }
        }
        //取消
        _debounce.cancel=()=>{
            timer=null;
            clearTimeOut(timer);
        }
        return _debounce;
    }
    //應用
    document.onmousemove=debounce(function(e){
        console.log("鼠標移動了");
        console.log(new Date().getUTCSeconds());
        console.log(e);//e是事件對象,
    },300,true);
複製代碼

輸出結果以下: git

二、函數節流

原理:節流就是在讓函數在特定的時間內只執行一次(持續觸發事件,每隔一段時間,只執行一次事件)。

代碼實現:github

function throtle(fn,await){
    let timer=null;
    let previousTime=0;
    let _throtle=()=>{
        let now=+new Date();//獲取當前時間戳
        let remain=now-previousTime
        if(remain>await){
            //下面的代碼只會在第一次觸發時執行(或者是間隔時間超過await後再次執行)
            if(timer){
                //清除定時器
                clearTimeOut(timer);
                timer=null
            }
            //此時now不等於+new Date()
            previousTime=+new Date();//當前時間,使用+獲取當前時間戳
            fn.apply(this,...arguments);
        }else if(!timer){//避免添加多個定時器
            timer=setTimeOut(()=>{
               timer=null;
               previousTime=+new Date();//當前時間
               fn.apply(this,...arguments);
            },remain);
        }
    }
    _throtle.cancel=()=>{
        timer=null;
        clearTimeOut(timer);
        previousTime=0;
    }
    return _throtle;
}
複製代碼

參考連接:
一、一個合格的中級前端工程師必需要掌握的 28 個 JavaScript 技巧
二、函數防抖
三、javaScript專題之跟着underscore學防抖
四、javaScript專題之跟着underscore學節流前端工程師

相關文章
相關標籤/搜索