防抖和節流嚴格算起來應該屬於前端性能優化的知識,但實際上遇到的頻率至關高,處理不當或者聽任無論就容易引發瀏覽器卡死。
舉例:不少網站會提供這麼一個按鈕:用於返回頂部。
這個按鈕會在滾動到距離頂部必定位置以後纔出現,功能需求-- 監聽瀏覽器滾動事件,返回當前滾條與頂部的距離前端
function showTop () { var scrollTop = document.body.scrollTop || document.documentElement.scrollTop; console.log('滾動條位置:' + scrollTop); } window.onscroll = showTop
在運行的時候會發現存在一個問題:這個函數的默認執行頻率過高了!瀏覽器
定義: 對於短期內連續觸發的事件,防抖的含義就是讓某個時間期限內,事件處理函數只執行一次。性能優化
基於上述場景,第一種解決思路:在第一次觸發事件時,不當即執行函數,而是給出一個延遲值好比200ms後執行,而後:閉包
結果:若是短期內大量觸發同一事件,只會執行一次函數。前端性能
實現:計時函數setTimeout
這個函數,須要一個變量來保存計時,考慮維護全局純淨,能夠藉助閉包來實現:函數
function debounce(fn,delay){ let timer = null //藉助閉包 return function() { if(timer){ clearTimeout(timer) } timer = setTimeout(fn,delay) // 簡化寫法 } } function showTop () { var scrollTop = document.body.scrollTop || document.documentElement.scrollTop; console.log('滾動條位置:' + scrollTop); } window.onscroll = debounce(showTop,1000)
上面的防抖方案來處理問題的結果是:性能
可是若是指望處理方案是:即便用戶不斷拖動滾動條,也能在某個時間間隔以後給出反饋呢?
分析:咱們能夠設計一種相似控制閥門同樣按期開放的函數,也就是讓函數執行一次後,在某個時間段內暫時失效,過了這段時間後再從新激活。優化
效果:若是短期內大量觸發同一事件,那麼在函數執行一次以後,該函數在指定的時間期限內再也不工做,直至過了這段時間才從新生效。網站
實現 setTimeout
和狀態位valid
來表示當前函數是否處於工做狀態:設計
function throttle(fn,delay){ let valid = true return function() { if(!valid){ return false } valid = false setTimeout(() => { fn() valid = true; }, delay) } } function showTop () { var scrollTop = document.body.scrollTop || document.documentElement.scrollTop; console.log('滾動條位置:' + scrollTop); } window.onscroll = throttle(showTop,1000)
結果:* 若是一直拖着滾動條進行滾動,那麼會以1s的時間間隔,持續輸出當前位置和頂部的距離