JS 防抖

沒有防抖:

var count = 1;
var container = document.getElementById('container');

function getUserAction() {
    container.innerHTML = count++;
};

container.onmousemove = getUserAction;

此時,鼠標移動,getUserAction方法就會頻繁的被觸發。醬紫可不好,浪費資源是吧。

防抖優化的第一版代碼

// 第一版
function debounce(func, wait) {
    var timeout;
    return function () {
        clearTimeout(timeout)
        timeout = setTimeout(func, wait);
    }
}

// 這裏用了高階函數trick,還用了閉包
container.onmousemove = debounce(getUserAction, 1000);

函數解析:

函數內部,保存了timeout這個延遲函數(定時器),然後返回了一個匿名函數作爲container.onmousemove的響應函數。

當用戶有鼠標移動的動作的時候,首先清理定時器,然後,新建一個定時器,在wait時間後,才執行getUserAction。

這樣,如果在wait時間內,鼠標移動函數又一次被觸發,上一個定時器就被清理,然後重新建立一個新的定時器,在wait時間後執行getUserAction。

這樣的結果就是,只有在wait時間內,鼠標動作沒有被再次觸發,函數getUserAction纔會被執行。

this和event

使用了debounce函數,可能會導致this丟失,我們需要修改一下代碼:

// 第二版
function debounce(func, wait) {
    var timeout;

    return function () {
        var context = this; // 作爲事件的直接響應函數,此時,this依舊指向document.getElementById('container')元素

        clearTimeout(timeout)
        timeout = setTimeout(function(){
            func.apply(context) // apply函數可以修改函數this的指向
        }, wait);
    }
}

下面,我們想辦法把event也傳進去

event會作爲debounce函數返回的匿名函數的參數。

// 第三版
function debounce(func, wait) {
    var timeout;

    return function () {
        var context = this;
        var args = arguments;

        clearTimeout(timeout)
        timeout = setTimeout(function(){
            func.apply(context, args)
        }, wait);
    }
}

於是我們修復了兩個問題:this指向,event對象。

發佈了344 篇原創文章 · 獲贊 39 · 訪問量 31萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章