函數節流和防抖

前言

瀏覽器中某些計算和處理要比其餘的昂貴不少。例如DOM操做比DOM交互須要更多的時間和cpu時間,爲了提高性能,減小DOM操做,因而,函數節流防抖和應運而生,其函數節流的基本思想是指,某些代碼不能夠在沒有間斷的狀況下連續重複執行。函數防抖的基本思想是指,一個頻繁觸發的事情只讓最後一次執行。下面就讓咱們來認真瞭解下這常常使用的函數節流和防抖。git

函數節流

函數節流:一個函數執行一次後,只有大於設定的執行週期後纔會執行第二次。有個須要頻繁觸發函數,出於優化性能角度,在規定時間內,只讓函數觸發的第一次生效,後面不生效。github

下面主要介紹時間戳和定時器兩種方式來實現節流函數。瀏覽器

  • 時間戳實現函數節流

根據函數節流的原理,咱們也能夠不依賴 setTimeout實現函數節流。app

function throttle(fn, delay) {
    // 記錄上一次函數觸發的時間
    var lastTime = 0;
    return function() {
        // 記錄當前函數觸發的時間
        var nowTime = Date.now();
        if (nowTime - lastTime > delay) {
        // 修正this指向問題
            fn.call(this);
        // 同步時間
          lastTime = nowTime;
        }
    }
}

測試代碼:函數

// test
function testThrottle(e, content) {
    console.log(e, content);
}
var testThrottleFn = throttle(testThrottle, 1000); // 節流函數
document.onmousemove = function (e) {
    testThrottleFn(e, 'throttle'); // 給節流函數傳參
}

其實現原理,經過比對上一次執行時間與本次執行時間的時間差與間隔時間的大小關係,來判斷是否執行函數。若時間差大於間隔時間,則馬上執行一次函數。並更新上一次執行時間。性能

  • 定時器實現函數節流
function throttle(fn, delay) {
    var timer;
    return function () {
        var _this = this;
        var args = arguments;
        if (timer) {
            return;
        }
        timer = setTimeout(function () {
            fn.apply(_this, args);
            timer = null; // 在delay後執行完fn以後清空timer,此時timer爲假,
            throttle觸發能夠進入計時器
        }, delay)
    }
}

測試代碼:測試

function testThrottle(e, content) {
    console.log(e, content);
}
var testThrottleFn = throttle(testThrottle, 2000); // 節流函數
document.onmousemove = function (e) {
    testThrottleFn(e, 'throttle'); // 給節流函數傳參
}

上面例子中,若是咱們一直在瀏覽器中移動鼠標(好比10s),則在這10s內會每隔2s執行一次testThrottle,這就是函數節流。優化

函數節流的目的,是爲了限制函數一段時間內只能執行一次。所以,定時器實現節流函數經過使用定時任務,延時方法執行。在延時的時間內,方法若被觸發,則直接退出方法。從而,實現函數一段時間內只執行一次。this

函數節流的應用場景

須要間隔必定時間觸發回調來控制函數調用頻率code

    • DOM 元素的拖拽功能實現(mousemove)
    • 搜索聯想(keyup)
    • 計算鼠標移動的距離(mousemove)
    • Canvas 模擬畫板功能(mousemove)
    • 滾動加載,加載更多或滾到底部監聽
    • 谷歌搜索框,搜索聯想功能
    • 高頻點擊提交,表單重複提交

    函數防抖

    防抖函數:一個須要頻繁觸發的函數,在規定時間內,只讓最後一次生效,前面的不生效。

    function debounce(fn, delay) {
        var timer = null; 
        return function () {
            var _this = this; // 取debounce執行做用域的this
            var args = arguments;
            if (timer) {
                clearTimeout(timer);
            }
            timer = setTimeout(function () {
                fn.apply(_this, args); // 用apply指向調用debounce的對象,
                至關於_this.fn(args);
            }, delay);
        };
    }

    測試代碼:

    function testDebounce(e, content) {
        console.log(e, content);
    }
    var testDebounceFn = debounce(testDebounce, 1000); // 防抖函數
    document.onmousemove = function (e) {
        testDebounceFn(e, 'debounce'); // 給防抖函數傳參
    }

    上面例子中的debounce就是防抖函數,在document中鼠標移動的時候,會在onmousemove最後觸發的1s後執行回調函數testDebounce;若是咱們一直在瀏覽器中移動鼠標(好比10s),會發現會在10+1s後纔會執行testDebounce函數(由於clearTimeout(timer)),這個就是函數防抖。

    函數防抖的應用場景

    對於連續的事件響應咱們只須要執行一次回調:

    • 每次 resize/scroll 觸發統計事件
    • 文本輸入的驗證(連續輸入文字後發送 AJAX 請求進行驗證,驗證一次就好)
    • 搜索框搜索輸入。只需用戶最後一次輸入完,再發送請求
    • 手機號、郵箱驗證輸入檢測
    • 窗口大小Resize。只需窗口調整完成後,計算窗口大小。防止重複渲染。

    總結

    函數節流和函數去抖的核心其實就是限制某一個方法被頻繁觸發,其目的都是,下降回調執行頻率,節省計算資源,提升瀏覽器的性能。

    更多優質文章能夠訪問GitHub博客,歡迎帥哥美女前來Star!!!

    相關文章
    相關標籤/搜索