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
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) } }
場景: