防抖和節流


防抖和節流的區別是什么? 防抖和節流的實現。

防抖和節流的作用都是防止函數多次調用。區別在於,假設一個用戶一直觸發這個函數,且每次觸發函數的間隔小於設置的時間,防抖的情況下只會調用一次,

且節流的情況會每隔一定時間調用一次函數。

防抖(debounce):n秒內函數只會執行一次,如果n秒內高頻事件再次被觸發,則重新計算時間。

function debounce(func, wait, immediate=true) {
    let timeout, context, args;
        // 延遲執行函數
        const later = () => setTimeout(() => {
            // 延遲函數執行完畢,清空定時器
            timeout = null
            // 延遲執行的情況下,函數會在延遲函數中執行
            // 使用到之前緩存的參數和上下文
            if (!immediate) {
                func.apply(context, args);
                context = args = null;
            }
        }, wait);
        let debounced = function (...params) {
            if (!timeout) {
                timeout = later();
                if (immediate) {
                    //立即執行
                    func.apply(this, params);
                } else {
                    //閉包
                    context = this;
                    args = params;
                }
            } else {
                clearTimeout(timeout);
                timeout = later();
            }
        }
    debounced.cancel = function () {
        clearTimeout(timeout);
        timeout = null;
    };
    return debounced;
};

防抖的應用場景:

1) 每次 resize / scroll 觸發統計事件

2) 文本輸入的驗證 (連續輸入文字后發送AJAX請求進行驗證,驗證一次就好)

 

節流 (throttle): 高頻事件在規定時間內只會執行一次,執行一次后,只有大於設定的執行周期后才會執行第二次。

//underscore.js
function throttle(func, wait, options) {
    var timeout, context, args, result;
    var previous = 0;
    if (!options) options = {};

    var later = function () {
        previous = options.leading === false ? 0 : Date.now() || new Date().getTime();
        timeout = null;
        result = func.apply(context, args);
        if (!timeout) context = args = null;
    };

    var throttled = function () {
        var now = Date.now() || new Date().getTime();
        if (!previous && options.leading === false) previous = now;
        var remaining = wait - (now - previous);
        context = this;
        args = arguments;
        if (remaining <= 0 || remaining > wait) {
            if (timeout) {
                clearTimeout(timeout);
                timeout = null;
            }
            previous = now;
            result = func.apply(context, args);
            if (!timeout) context = args = null;
        } else if (!timeout && options.trailing !== false) {
            // 判斷是否設置了定時器和 trailing
            timeout = setTimeout(later, remaining);
        }
        return result;
    };

    throttled.cancel = function () {
        clearTimeout(timeout);
        previous = 0;
        timeout = context = args = null;
    };

    return throttled;
};

函數節流的應用場景有:

1) DOM元素的拖拽功能實現(mousemove)

2) 射擊游戲的 mousedown / keydown 事件 (單位時間只能發射一顆子彈)

3) 計算鼠標移動的距離 (mousemove)

4) Canvas模擬畫板功能 (mousemove)

5) 搜索聯想(keyup)

6) 監聽滾動事件判斷是否到頁面底部自動加載更多:給scroll加了debounce后,

只有用戶停止滾動后,才會判斷是否到了頁面底部;如果是 throttle 的話,只要頁面滾動就會間隔一段時間判斷一次。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM