js中的防抖和節流

防抖和節流嚴格算起來應該屬於前端性能優化的知識,但實際上遇到的頻率至關高,處理不當或者聽任無論就容易引發瀏覽器卡死。
舉例:不少網站會提供這麼一個按鈕:用於返回頂部。
這個按鈕會在滾動到距離頂部必定位置以後纔出現,功能需求-- 監聽瀏覽器滾動事件,返回當前滾條與頂部的距離前端

function showTop  () {
    var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
  console.log('滾動條位置:' + scrollTop);
}
window.onscroll  = showTop

在運行的時候會發現存在一個問題:這個函數的默認執行頻率過高了!瀏覽器

防抖(debounce)

定義: 對於短期內連續觸發的事件,防抖的含義就是讓某個時間期限內,事件處理函數只執行一次。性能優化

基於上述場景,第一種解決思路:在第一次觸發事件時,不當即執行函數,而是給出一個延遲值好比200ms後執行,而後:閉包

  • 若是在200ms內沒有再次觸發滾動事件,那麼就執行函數
  • 若是在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)

節流(throttle)

上面的防抖方案來處理問題的結果是:性能

  • 若是在限定時間段內,不斷觸發滾動事件(好比某個用戶閒着無聊,按住滾動不斷的拖來拖去),只要不中止觸發,理論上就永遠不會輸出當前距離頂部的距離。

可是若是指望處理方案是:即便用戶不斷拖動滾動條,也能在某個時間間隔以後給出反饋呢?
分析:咱們能夠設計一種相似控制閥門同樣按期開放的函數,也就是讓函數執行一次後,在某個時間段內暫時失效,過了這段時間後再從新激活優化

效果:若是短期內大量觸發同一事件,那麼在函數執行一次以後,該函數在指定的時間期限內再也不工做,直至過了這段時間才從新生效。網站

實現 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的時間間隔,持續輸出當前位置和頂部的距離

相關文章
相關標籤/搜索