函數節流:在指定的間隔時間內只執行一次
有個須要頻繁觸發函數,出於優化性能角度,在規定時間內,只讓函數觸發的第一次生效,後面不生效。
好比下面的例子,在不加函數節流的時候,每當滾動條滾動的時候都會觸發一次,形成大量的性能浪費閉包
// 未添加節流函數 document.onscroll = function () { console.log('scroll事件被觸發了') }
添加了節流函數後app
// 添加了節流函數 document.onscroll = throttle(function () { console.log('scroll事件被觸發了') }, 300)
具體代碼實現函數
/** * @description 函數節流 * @param {Function} fn 須要執行函數節流的函數 * @param {Number} interval 指定間隔時間 */ function throttle(fn, interval = 300) { let canRun = true // 經過閉包保存一個標記 return function () { if (!canRun) return // 第一次調用執行 canRun = false // setTimeout未執行時,後續fn函數調用都不會再執行 // setTimeout 定時器延時執行 setTimeout(() => { fn.apply(this, arguments) canRun = true // 標記爲true,節流完成 }, interval) } }
代碼解釋
簡單來講,函數的節流就是經過閉包保存一個標記(canRun = true
), 在函數的開頭判斷這個標記是否爲true
,若是這個標記爲true
的話就繼續執行,不然就return
掉,判斷完標記後當即把這個標記設置爲false
,而後把外部傳入的函數的執行包在一個setTimout
中,最後在定時器執行完畢以後再把標記設置爲true
,表示本次延遲執行完畢,能夠執行下一次循環了。當定時器還未執行完畢的時候,canRun
這個標記始終未false
,故在開頭的判斷中老是被return
掉,函數並未執行。、
應用場景
監聽滾動事件判斷是否到頁面底部自動加載更多:給 scroll 加了 debounce 後,只有用戶中止滾動後,纔會判斷是否到了頁面底部;若是是 throttle 的話,只要頁面滾動就會間隔一段時間判斷一次等性能
函數防抖: 一個須要頻繁觸發的函數,在規定時間內,只讓最後一次生效,前面的不生效。
好比點擊一個按鈕,每點擊一次就會觸發一次事件,在沒有加防抖函數的狀況下,快速點擊會致使屢次觸發優化
// 未加防抖函數 document.getElementById('btn').onclick = function(){ console.log('我被點擊了'); }
在加了防抖函數後,只會在規定時間後觸發一次this
// 加了防抖函數 document.getElementById('btn').onclick = debounce(function(){ console.log('我被點擊了'); },300)
具體代碼實現code
/** * @description 函數防抖 * @param {Function} fn 須要執行函數防抖的函數 * @param {Number} interval 指定間隔時間 */ function debounce(fn, interval = 300) { let timeout = null // 經過閉包保存一個標記 return function () { clearInterval() // 把前一個定時器去掉 // 又建立一個新的定時器 timeout = setTimeout(() => { fn.apply(this, arguments) // 指定的時間間隔以後運行fn }, interval) } }
代碼解釋
其原理就第一次調用函數,建立一個定時器,在指定的時間間隔以後運行代碼。當第二次調用該函數時,它會清除前一次的定時器並設置另外一個。若是前一個定時器已經執行過了,這個操做就沒有任何意義。然而,若是前一個定時器還沒有執行,其實就是將其替換爲一個新的定時器,而後延遲必定時間再執行。
應用場景
文本輸入的驗證(連續輸入文字後發送 AJAX 請求進行驗證,驗證一次就好)blog