函數節流和防抖

引言:bash

在咱們的開發過程當中都會遇到高頻事件,好比說onscroll事件,每當頁面滾動的時候,每一秒可能會觸發幾十次的函數執行, 假如onscroll還綁定了回調函數,並對dom進行重排,那麼每一秒執行幾十次dom渲染,若是dom操做過多,那麼頁面可能會出現卡頓的現象。app

或者resize行爲每一次頁面窗口的變化都會綁定dom的渲染也會出現上述狀況。爲了優化高頻事件(oninput,onkeyup,onkeydown),下降代碼執行頻率,採用優化方案函數的迴流和防抖。dom

函數節流 (throttle)

函數在必定時間內執行一次核心代碼。好比人在一段時間眨一次眼睛。函數

let btn = document.getElementById('btn')

        function logger() {
            console.log('logger') // 每一秒打印一次
        }

        function throttle(func, wait) {
            let previous = 0
            return function() {
                let now = Date.now()
                if (now - previous > wait) {
                    func.apply(this, arguments)
                    previous = now
                }
            }
        }
        btn.addEventListener('click', throttle(logger, 1000))
複製代碼

logger函數用來測試,正常每次點擊都會打印'logger', 節流處理每一秒打印一次'logger'測試

previous 相對於上一次點擊的時間 now 每次點擊記錄的事件優化

now - previous > wait 第一次由於previous 爲 0 第一次執行 logger函數, 把previous 賦值爲當前時間ui

第二次的時候只有當前時間和上次時間大於 wait(1000毫秒)的時候纔會再次執行loggerthis

對throttle函數優化

用戶最後一次的點擊事件觸發無論是否小於wait這裏是1s咱們須要記錄下來,觸發一次loggerspa

function throttle(func, wait, options) {
            let previous = 0
            let timer;
            let me = this;
            let later = function() {
                previous = Date.now()
                func.apply(me, arguments)
            }
            let throttled = function() {
                let now = Date.now();
                let remaining = wait - (now - previous); 
                if (remaining <= 0) {  // 小於0 說明點擊事件間隔大於1000ms
                    if (timer) {
                        clearTimeout(timer)
                        timer = null
                    }
                    func.apply(me, arguments)
                    previous = now
                } else if (!timer && options.trailing) {
                    timer = setTimeout(later, remaining)
                }
            }
            return throttled
        }
        btn.addEventListener('click', throttle(logger, 1000, { trailing: true}))
複製代碼

trailing等於 true開啓模式code

點擊事件時間間隔越短並小於1s ,now-previous值越小, 那麼 wait - (now - previous)值必定大於0 remaining > 0

第一次click !timer && options.trailing 成立, 結束後多執行一次later

下一次 先清除timer 再進入判斷 執行下一次later

函數防抖 (debounce)

函數在執行完畢的時候,才觸發核心代碼執行, 好比在作電梯的時候,若是關門的過程當中,有人要上來,不會走,等他上來一塊走。

function logger() {
      console.log('logger')
  }
  function debounce(func, wait) {
      let timeout;
      return function() {
        clearTimeout(timeout)
        timeout = setTimeout(() => {
            func.apply(this, arguments)
             timeout = null
        }, wait)
      }
  }
  btn.addEventListener('click', debounce(logger, 1000))
複製代碼

每次高頻率click的時候都會清除上一次的定時器不會執行代碼, 只有等到鬆開1s後纔會執行代碼

函數防抖優化

每次第一次點擊的時候先執行一次

function logger() {
      console.log('logger')
  }
  function debounce(func, wait, immediate) {
    let timeout;
      return function() {
        clearTimeout(timeout)
        if(immediate) {
            let callNow = !timeout
            if(callNow) func.apply(this, arguments)
        }
        timeout = setTimeout(() => {
            func.apply(this, arguments)
            timeout = null
        }, wait)
      }
  }
  btn.addEventListener('click', debounce(logger, 1000, true))
複製代碼

參考資料

underscore

相關文章
相關標籤/搜索