函數節流與函數防抖

函數節流(throttle)

函數節流:在指定的間隔時間內只執行一次
有個須要頻繁觸發函數,出於優化性能角度,在規定時間內,只讓函數觸發的第一次生效,後面不生效。
好比下面的例子,在不加函數節流的時候,每當滾動條滾動的時候都會觸發一次,形成大量的性能浪費閉包

// 未添加節流函數
document.onscroll = function () {
  console.log('scroll事件被觸發了')
}

添加了節流函數後app

// 添加了節流函數
document.onscroll = throttle(function () {
  console.log('scroll事件被觸發了')
}, 300)


具體代碼實現函數

/**
 * @description 函數節流
 * @param {Function} fn 須要執行函數節流的函數
 * @param {Number} interval 指定間隔時間
 */
function throttle(fn, interval = 300) {
  let canRun = true // 經過閉包保存一個標記
  return function () {
    if (!canRun) return // 第一次調用執行
    canRun = false // setTimeout未執行時,後續fn函數調用都不會再執行
    // setTimeout 定時器延時執行
    setTimeout(() => {
      fn.apply(this, arguments)
      canRun = true // 標記爲true,節流完成
    }, interval)
  }
}

代碼解釋
簡單來講,函數的節流就是經過閉包保存一個標記(canRun = true), 在函數的開頭判斷這個標記是否爲true,若是這個標記爲true的話就繼續執行,不然就return掉,判斷完標記後當即把這個標記設置爲false,而後把外部傳入的函數的執行包在一個setTimout中,最後在定時器執行完畢以後再把標記設置爲true,表示本次延遲執行完畢,能夠執行下一次循環了。當定時器還未執行完畢的時候,canRun這個標記始終未false,故在開頭的判斷中老是被return掉,函數並未執行。、
應用場景
監聽滾動事件判斷是否到頁面底部自動加載更多:給 scroll 加了 debounce 後,只有用戶中止滾動後,纔會判斷是否到了頁面底部;若是是 throttle 的話,只要頁面滾動就會間隔一段時間判斷一次等性能

函數防抖(debounce)

函數防抖: 一個須要頻繁觸發的函數,在規定時間內,只讓最後一次生效,前面的不生效。
好比點擊一個按鈕,每點擊一次就會觸發一次事件,在沒有加防抖函數的狀況下,快速點擊會致使屢次觸發優化

// 未加防抖函數
document.getElementById('btn').onclick = function(){
  console.log('我被點擊了');
}

在加了防抖函數後,只會在規定時間後觸發一次this

// 加了防抖函數
document.getElementById('btn').onclick = debounce(function(){
  console.log('我被點擊了');
},300)

具體代碼實現code

/**
 * @description 函數防抖
 * @param {Function} fn 須要執行函數防抖的函數
 * @param {Number} interval 指定間隔時間
 */
function debounce(fn, interval = 300) {
  let timeout = null // 經過閉包保存一個標記
  return function () {
    clearInterval() // 把前一個定時器去掉
    // 又建立一個新的定時器
    timeout = setTimeout(() => {
      fn.apply(this, arguments) // 指定的時間間隔以後運行fn
    }, interval)
  }
}

代碼解釋
其原理就第一次調用函數,建立一個定時器,在指定的時間間隔以後運行代碼。當第二次調用該函數時,它會清除前一次的定時器並設置另外一個。若是前一個定時器已經執行過了,這個操做就沒有任何意義。然而,若是前一個定時器還沒有執行,其實就是將其替換爲一個新的定時器,而後延遲必定時間再執行。
應用場景
文本輸入的驗證(連續輸入文字後發送 AJAX 請求進行驗證,驗證一次就好)blog

相關文章
相關標籤/搜索