概念
函數防抖(debounce)
當調用動作過n毫秒后,才會執行該動作,若在這n毫秒內又調用此動作則將重新計算執行時間
函數節流(throttle)
預先設定一個執行周期,當調用動作的時刻大於等於執行周期則執行該動作,然后進入下一個新周期
函數節流(throttle)與 函數防抖(debounce)都是為了限制函數的執行頻次,以優化函數觸發頻率過高導致的響應速度跟不上觸發頻率,出現延遲,假死或卡頓的現象。
比如如下的情況:
- window對象的resize、scroll事件
- 拖拽時的mousemove事件
- 文字輸入、自動完成的keyup事件
區別
可以拿我們平時坐電梯為例來形象地表述二者的區別
函數防抖:如果有人進電梯(觸發事件),那電梯將在10秒鍾后出發(執行事件監聽器),這時如果又有人進電梯了(在10秒內再次觸發該事件),我們又得等10秒再出發(重新計時)。函數節流 :保證如果電梯第一個人進來后,10秒后准時運送一次,這個時間從第一個人上電梯開始計時,不等待,如果沒有人,則不運行
實現
函數防抖(debounce)
function _debounce(fn,wait){ var timer = null; return function(){ clearTimeout(timer) timer = setTimeout(()=>{ fn() },wait) } } function _log(){ console.log(1) } window.onscroll = _debounce(_log,500)
函數節流(throttle)
仔細想想,上面的防抖方式還是有一定的缺點。如果頁面很長,我們一直在滾動頁面,那_log方法就一直不會被執行。所以我們可以升級一下上述的防抖方法。
function _throttle(fn,wait,time){ var previous = null; //記錄上一次運行的時間 var timer = null; return function(){ var now = +new Date(); if(!previous) previous = now; //當上一次執行的時間與當前的時間差大於設置的執行間隔時長的話,就主動執行一次 if(now - previous > time){ clearTimeout(timer); fn(); previous = now;// 執行函數后,馬上記錄當前時間 }else{ clearTimeout(timer); timer = setTimeout(function(){ fn(); },wait); } } } function _log(){ console.log(1) } window.onscroll = _throttle(_log,500,2000)