函式防抖和節流
在網上,關於防抖和節流的實現方式已經很多了,這裡也就不在依依列舉,只是說說這兩種思想方式,要注意,函式防抖和節流只是一種解決問題的設計思想罷了。
思想緣由
在瀏覽器中,頻繁的操作 DOM 是非常消耗記憶體和 CPU 時間,在我們專案開發過程中,或多或少會繫結一些持續觸發的事件,如 resize,scroll,mousemove 以及移動端 touchmove 等。同一個事件在同一刻產生大量的事件函式,若處理不當,輕則導致瀏覽器卡頓,重則導致瀏覽器崩潰,無論出現哪種情況,都不是我們所期望的,此時,函式防抖 (debounce) 和節流 (throttle) 的思想應運而生。
函式防抖和節流就是為了處理同一時刻事件的觸發頻率和事件函式的執行頻率這兩者關係的。 我們知道 DOM 事件的觸發頻率是不可控的,因此我們只能控制事件函式的執行頻率,只要是沒有達到條件要求的事件,都不觸發事件函式,通過這一手段,可以極大的優化瀏覽器的效能。
函式防抖
函式防抖是指某事件被頻繁的觸發,在延遲一定的時間內,若該事件沒有繼續被觸發,則執行事件函式,在整個過程中,事件函式只會被觸發一次。
應用場景:在事件連續觸發過程中,你期望事件函式只執行一次,例如:Ajax實時搜尋(keydown)。
舉個例子,我們在瀏覽頁面內容的時候經常會使用到滾動條,若此時我們綁定了一個滾動條事件,但是,並沒有加任何的防抖保護,這意味著使用者只要觸動了滾動條,就會產生成百上千條滾動事件,進而觸發成百上千次事件函式,若每條事件函式的時間複雜度為O(n²),後果可想而知,直接把瀏覽器搞崩了,這樣的產品,還沒開始,已經結束了。
此時,若加上防抖,效果就大大的不同了, 我們雖然無法阻止事件的觸發頻率,但是可以控制事件函式的執行頻率 ,無論你觸發了多少次事件,只要在保護時間內有觸發,就不執行事件函式,反之,執行。
沒有什麼能比圖片更形象的了:point_down:

function debounce(func, wait) { let timeout = null; return function() { let _this = this; let args = arguments; if (timeout) { clearTimeout(timeout) } timeout = setTimeout(() => { func.apply(_this, args) ), wait) } } 複製程式碼
防抖的核心就是通過定時器來延遲事件函式的執行,在未達到定時器時間情況下,依舊產生了觸發事件,就將上一個定時器刪除。
函式節流
函式節流是指某事件被頻繁的觸發,在事件觸發期間,它會週期的執行事件函式。
舉個例子,水滴的下落,我們將水喉撥到一個角度,水滴會週期性一滴一滴的滴落。
應用場景:在事件連續觸發過程中,你期望週期性的間隔一定時間來呼叫回撥函式,例如:計算滑鼠移動的距離(mousemove)

function (func, wait) { let time = null; return function() { let _this = this; let args = arguments; if (!timer) { timer = setTimeout(function() { func.apply(_this, args) timer = null }, delay) } } } 複製程式碼