天天看點

原生js函數防抖

 函數防抖主要就是防止頻繁觸發事件就會頻繁觸發回調,回調要是操作dom或者其他耗時工作,浏覽器受不了。

函數防抖:

好比電梯需要上人,來一個人,就要等幾秒再走,再來個人又要多等一樣的時間,再來一樣。

在網上看到也有個比較恰當的比喻,好比網絡遊戲法師施法,點選之後正在讀進度條,你又點了一次,那隻能從頭再讀,每次點都得從頭讀。

實作代碼如下:

function debounce (func, wait) {
  var lastCallTime
  var lastThis
  var lastArgs
  var timerId
  function startTimer (timerExpired, wait) {
    return setTimeout(timerExpired, wait)
  }

  function remainingWait(time) {
    const timeSinceLastCall = time - lastCallTime
    const timeWaiting = wait - timeSinceLastCall
    return timeWaiting
  }

  function shoudInvoking (time) {
    return lastCallTime !== undefined && (time - lastCallTime >= wait)
  }

  function timerExpired () {
    const time = Date.now()
    // 一個勁猛點的話這個if裡永遠滿足不了條件,隻有你停下來等一會,就會有結果了
    if (shoudInvoking(time)) {
      return invokeFunc()
    }
    timerId = startTimer(timerExpired, remainingWait(time))
  }

  function invokeFunc () {
    timerId = undefined
    const args = lastArgs
    const thisArg = lastThis
    let result = func.apply(thisArg, args)
    lastArgs = lastThis = undefined
    return result
  }

  function debounced (...args) {
    let time = Date.now()
    lastThis = this
    lastArgs = args
    lastCallTime = time
    // invokeFunc函數沒結果之前,再點選多少次下邊這個函數都不執行了.點選隻會更改lastCallTime
    // 更改了lastCallTime,
    if (timerId === undefined) {
      timerId = startTimer(timerExpired, wait)
    }
  }

  return debounced
}

window.addEventListener('click', debounce(function (event) {
  var p = document.createElement('p')
  p.innerHTML = 'trigger'
  document.body.appendChild(p)
  return 'aaaa'
}, 500))
           

可以使用lodash 中的 debounce函數。省去自己寫的麻煩。但是原理了解一下,沒壞處。

繼續閱讀