「節流」,字典上這麼解釋:javascript
[throttle]∶節制流入或流出,尤指用節流閥調節。java
那節流函數 (throttle) 就是 「節制流入或流出的函數」,愈來愈繞了,這是什麼鬼?剛開始接觸這種名詞,反正我是有點摸不着頭腦,略抽象,很差理解。函數
那放下這術語無論,先看看爲何要用它。性能
頁面事件中,scroll, resize 和 mousemove 事件都有一個共同點,就是會頻繁地被觸發。舉個例子,那 scroll 來看好了。ui
先寫一段代碼:spa
let num = 1
window.onscroll = () => {
console.log(num++)
}
複製代碼
這裏監聽了頁面的 scroll 事件,當頁面滾動時,打印出遞增的數字。3d
下圖是運行結果,能夠看到,console 裏面瘋狂輸出: code
回想一下最經常使用的 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 這些事件的回調函數。