js中的函數防抖與節流

1、滾動條監聽的例子chrome

  寫一個功能需求-- 監聽瀏覽器滾動事件,返回當前滾條與頂部的距離,代碼以下:瀏覽器

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

  可是在運行的時候會發現存在一個問題:這個函數的默認執行頻率,太!高!了!。 閉包

  以chrome爲例,咱們能夠點擊選中一個頁面的滾動條,而後點擊一次鍵盤的向下方向鍵,會發現函數執行了8-9次函數

  瀏覽器的性能是有限的,不該該浪費在這裏,因此接着討論如何優化這種場景。性能

2、防抖(debounce) 優化

  定義在事件被觸發n秒後再執行回調,若是在這n秒內又被觸發,則從新計時spa

       實現:實現的關鍵就在於setTimeOut這個函數,因爲還須要一個變量來保存計時,考慮維護全局純淨,能夠藉助閉包來實現。code

/*
* fn [function] 須要防抖的函數
* delay [number] 毫秒,防抖期限值
*/
function debounce(fn,delay){
    let timer = null //藉助閉包
    return function() {
        if(timer){
            clearTimeout(timer) //進入該分支語句,說明當前正在一個計時過程當中,而且又觸發了相同事件。因此要取消當前的計時,從新開始計時
            timer = setTimeOut(fn,delay) 
        }else{
            timer = setTimeOut(fn,delay) // 進入該分支說明當前並無在計時,那麼就開始一個計時
        }
    }
}

      場景blog

  • 鼠標/觸摸屏的mouseover/touchmove事件
  • 頁面窗口的resize事件
  • 滾動條的scroll事件

3、節流(throttle)seo

     定義規定在一個單位時間內,只能觸發一次函數。若是這個單位時間內觸發屢次函數,只有一次生效

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

   藉助setTimeout來作一個簡單的實現,加上一個狀態位valid來表示當前函數是否處於工做狀態:

function throttle(fn,delay){
    let valid = true
    return function() {
       if(!valid){
           //休息時間 暫不接客
           return false 
       }
       // 工做時間,執行函數而且在間隔期內把狀態位設爲無效
        valid = false
        setTimeout(() => {
            fn()
            valid = true;
        }, delay)
    }
}

  場景:

  • 按鈕點擊事件,防止用戶屢次重複提交
  • API的調用
相關文章
相關標籤/搜索