摘要:JavaScript 中的函數(shù)防抖和節(jié)流是很常用的需求,前端面試也是頻率比較高被問到的知識,本文就通過二者的概念、實現(xiàn)思路家妆、示例代碼和應用場景來介紹一下它們。
概念
函數(shù)防抖(debounce):其概念其實是從機械開關和繼電器的“去彈跳”(debounce)衍生出來的冕茅,基本思路就是把多個信號合并為一個信號伤极。比如一個
input
每當輸入結束后兩秒執(zhí)行搜索事件,這就是個很經(jīng)典的防抖需求姨伤。函數(shù)節(jié)流(throttle):節(jié)流的概念可以想象一下水壩哨坪,你建了水壩在河道中,不能讓水流動不了乍楚,你只能讓水流慢些当编。換言之,你不能讓用戶的方法都不執(zhí)行徒溪。如果這樣干忿偷,就是debounce了。為了讓用戶的方法在某個時間段內(nèi)只執(zhí)行一次臊泌,我們需要保存上次執(zhí)行的時間點與定時器鲤桥。
思路
函數(shù)防抖的實現(xiàn)思路如下:將目標方法(動作)包裝在setTimeout里面,然后這個方法是一個事件的回調(diào)函數(shù)渠概,如果這個回調(diào)一直執(zhí)行茶凳,那么這些動作就一直不執(zhí)行。為什么不執(zhí)行呢高氮,我們設置了一個clearTimeout慧妄,這樣setTimeout里的方法就不會執(zhí)行! 為什么要clearTimeout呢剪芍,我們就需要將事件內(nèi)的連續(xù)動作刪掉嘛塞淹!待到用戶不觸發(fā)這事件了。那么setTimeout就自然會執(zhí)行這個方法罪裹。
函數(shù)節(jié)流的實現(xiàn)思路如下:某些代碼不可以在沒有間斷的情況連續(xù)重復執(zhí)行饱普。第一次調(diào)用函數(shù),創(chuàng)建一個定時器状共,在指定的時間間隔之后運行代碼套耕。當?shù)诙握{(diào)用該函數(shù)時,它會清除前一次的定時器并設置另一個峡继。如果前一個定時器已經(jīng)執(zhí)行過了冯袍,這個操作就沒有任何意義。然而,如果前一個定時器尚未執(zhí)行康愤,其實就是將其替換為一個新的定時器儡循。目的是只有在執(zhí)行函數(shù)的請求停止了一段時間之后才執(zhí)行。
代碼
函數(shù)防抖示例代碼:
function debounce(func, delay) {
let timeout
return function(e) {
clearTimeout(timeout)
let args = arguments
timeout = setTimeout(() => {
func.apply(this, args)
},delay)
}
}
var validate = debounce(function(e) {
console.log( e.target.value)
}, 2000)
document.querySelector("input").addEventListener('input', validate)
函數(shù)節(jié)流示例代碼:
function debounce(func, delay) {
let timeout
return function(e) {
clearTimeout(timeout)
let args = arguments
timeout = setTimeout(() => {
func.apply(this, args)
},delay)
}
}
var validate = debounce(function(e) {
console.log( e.target.value)
}, 2000)
document.querySelector("input").addEventListener('input', validate)
應用場景
防抖 debounce 多用于 “ 延遲多久后觸發(fā) ”
具體用于input輸入框架的格式驗證征冷,假如只是驗證都是字母也罷了择膝,太簡單了,不怎么耗性能检激,如果是驗證是否身份證肴捉,這性能消耗大,你可以隔170ms才驗證一次叔收。這時就需要這個東西齿穗。或者你這個是自動完全今穿,需要將已有的輸入數(shù)據(jù)往后端拉一個列表缤灵,頻繁的交互,后端肯定耗不起蓝晒,這時也需要這個腮出,如隔 350ms 。
所以大致就有以下兩種應用情景:
- 每次 resize/scroll 觸發(fā)統(tǒng)計事件
- 文本輸入的驗證(連續(xù)輸入文字后發(fā)送 AJAX 請求進行驗證芝薇,驗證一次就好)
節(jié)流 throttle 多用于 “ 多久觸發(fā)一次 ”
函數(shù)節(jié)流會用在比input, keyup更頻繁觸發(fā)的事件中胚嘲,如resize, touchmove, mousemove, scroll。throttle 會強制函數(shù)以固定的速率執(zhí)行洛二。因此這個方法比較適合應用于動畫相關的場景馋劈。
- DOM 元素的拖拽功能實現(xiàn)(mousemove)
- 射擊游戲的 mousedown/keydown 事件(單位時間只能發(fā)射一顆子彈)
- 計算鼠標移動的距離(mousemove)
- Canvas 模擬畫板功能(mousemove)
- 搜索聯(lián)想(keyup)
- 監(jiān)聽滾動事件判斷是否到頁面底部自動加載更多:給 scroll 加了 debounce 后,只有用戶停止?jié)L動后晾嘶,才會判斷是否到了頁面底部妓雾;如果是 throttle 的話,只要頁面滾動就會間隔一段時間判斷一次
相關鏈接
(END)