javascript函數防抖

函數防抖 (debounce)

函數防抖是頻繁發生的狀況下,當有足夠的空閒時間,纔會執行代碼一次,是優化高頻率執行代碼的一種手段。實際開發中會遇到頻發觸發事件的狀況,好比 resize, scroll, mousemove 事件。html

原理

事件觸發 n 秒後執行,若是在這 n 秒內再次觸發,則以新的事件時間爲準,n 秒後執行。不管觸發多少次,都要等到最後一次觸發 n 秒後才執行。app

實現

mousemove舉例,當鼠標移入時,在 div 內顯示事件函數執行的次數。防抖的簡單實現以下:函數

<div id='container'></div>
let count = 0;
let oDiv = document.querySelector('#container');

//防抖函數
function debounce(fn, delay) {
    let timer;
    
    return function() {
        clearTimeout(timer);
        timer = setTimeout(fn, delay);
    }
}

//事件函數
function eventFn() {
    oDiv.innerHTML = ++count;
}

oDiv.onmousemove = debounce(eventFn, 1000);

this指向

正常狀況下,在事件函數中使用 this 指向該事件綁定的元素。而此時 eventFn 是做爲定時器的一個參數,this 指向 window ,須要更正 this 指向。優化

function debounce(fn, delay) {
    let timer;
    
    return function() {
        let _this = this;
        
        clearTimeout(timer);
        timer = setTimeout(function () {
            fn.apply(_this);
        }, delay);
    }
}

event對象

通常狀況下,事件函數 eventFn 的第一個參數爲 event 對象,但此時,值爲 undefined。修改防抖函數:this

function debounce(fn, delay) {
    let timer;
    
    return function() {
        let _this = this;
        let opt = arguments;
        
        clearTimeout(timer);
        timer = setTimeout(function () {
            fn.apply(_this, arguments);
        }, delay);
    }
}

當即執行

防抖函數中使用了定時器,事件觸發後會延遲必定時間才調用事件函數,有時咱們但願觸發事件能夠當即執行,而後須要 n 秒後才能從新觸發執行。咱們經過傳入第三個參數,判斷是否須要當即執行。code

function debounce(fn, delay, immediate) {
    let timer;
    
    return function() {
        let _this = this;
        let opt = arguments;
        
        timer && clearTimeout(timer);
        if(immediate) {
            let call = !timer;
            timer = setTimeout(function() {
                timer = false;
            }, delay);
            
            call && fn.apply(_this, opt);
        } else {
            timer = setTimeout(function() {
                 fn.apply(_this, opt);
             }, delay);
        }    }
}
相關文章
相關標籤/搜索