JavaScript 節流函數

簡介

「節流」,字典上這麼解釋:javascript

[throttle]∶節制流入或流出,尤指用節流閥調節。java

那節流函數 (throttle) 就是 「節制流入或流出的函數」,愈來愈繞了,這是什麼鬼?剛開始接觸這種名詞,反正我是有點摸不着頭腦,略抽象,很差理解。函數

那放下這術語無論,先看看爲何要用它。性能

場景

頁面事件中,scroll, resize 和 mousemove 事件都有一個共同點,就是會頻繁地被觸發。舉個例子,那 scroll 來看好了。ui

先寫一段代碼:spa

let num = 1
window.onscroll = () => {
  console.log(num++)
}
複製代碼

這裏監聽了頁面的 scroll 事件,當頁面滾動時,打印出遞增的數字。3d

下圖是運行結果,能夠看到,console 裏面瘋狂輸出: code

before_throttle.gif

回想一下最經常使用的 click 事件,是否是老老實實,點一次,執行一次。而 scroll 呢,滾動一小段,好幾回就去了。這裏還好,不涉及到 DOM 操做,要是在 scroll 事件中處理 DOM 元素,那頁面性能確定受到影響,筆記本風扇說不定隨着滾動的頁面呼呼做響,或者頁面一卡一卡卡出心髒病。cdn

讓它消停點的辦法,就是讓回調少執行幾回。提到讓瘋狂執行的函數少執行幾回,限制它的行爲,「節流」這個概念是否是隱隱約約出現,再也不那麼抽象了?就比如把水龍頭關小一點,讓水慢慢流。blog

方法

怎麼讓這個函數慢慢流呢?

設想一下,頁面一直在滾動,根本停不下來。這個時候,回調也一直在觸發,噼裏啪啦。

和它商量一下: 「你能不能隔幾秒執行一次?」

"隔幾秒?"

"兩百毫秒吧。"

節流函數就是給這種高頻率觸發的函數,規定一個時間間隔,就是這一次執行和下一次執行的時間間隔。

有點像遊戲裏面的技能冷卻時間,放了技能,進入冷卻時間,這期間,就算不停地點技能,也放不了,只能等冷卻好,再放。

千言萬語不如上代碼:

const throttle = (func, ms = 200) => {
  let prev = new Date().getTime()
  return function(...args) {
    let now = new Date().getTime()
    if (now - prev >= ms) {
      func()
      prev = now
    }
  }
}

複製代碼

這裏的 throttle 函數接受一個函數 func 和一個毫秒數 ms 做爲參數,返回一個函數。當返回的函數不停地被觸發,只有知足兩次觸發間隔大於或者等於規定的毫秒數,傳入的 func 才執行。

這個間隔是用時間戳來判斷的。首先定義變量 prev 記錄一個時間,在返回的函數中,取得它執行時的時間戳 now,比較兩個時間戳,假如間隔大於規定的毫秒數 ms,就執行傳入的 func 函數。

拿上面的例子再舉個例子:

let num = 1
window.onscroll = throttle(()=> {console.log(num++)}, 2000)
複製代碼

這裏監聽頁面滾動事件,每兩秒觸發一次回調函數。以下所示(沒有慢放):

固然,實際開發中,不會兩秒一次這麼誇張。這裏只是爲了更明顯地觀察到節流函數的做用。

總結

節流函數爲高頻率觸發的回調設定一個執行週期,減小對頁面性能的損耗。

可用於 resize, scroll, mousemove 這些事件的回調函數。

相關文章
相關標籤/搜索