一個使用場景:
某些瀏覽器事件可能會在短期內高頻觸發,好比:整窗口大小或滾動頁面。
若是給窗口滾動事件添加一個事件監聽器,而後用戶不停地快速滾動頁面,那你的事件可能在短短數秒以內被觸發數千次。這會致使很是嚴重的性能問題。
因此若是功能涉及滾動事件,窗口調整事件,或者鍵盤事件鼠標事件等,你可能須要警覺起來,是否有必要使用 debouncing 或者 throttling 來提升頁面速度與性能。git
debouncing(防抖動)是解決上述問題的一個方案,它的作法是 限制下次函數調用以前必須等待的時間間隔,也就是說:強制一個函數在某個連續時間段內只執行一次,哪怕它原本會被調用屢次。正確實現 debouncing 的方法是:將若干個函數調用合併爲一次,只有在空閒時間大於或等於給定值的時候,才執行調用方法。github
簡單的實現一個 debounce
方法,接收兩個參數,一個是須要防抖動的函數 fn
,另外一個是延遲時間delay
瀏覽器
funciton debouncing(fn, delay) { let timer; //定時器 return function() { // 保存函數調用時的上下文和參數,傳遞給 fn const context = this; const args = arguments; clearTimeout(timer); timer = setTimeout(function(){ fn.apply(context, args); }, delay); } }
該 debounce
的使用方法以下:app
$(document).on('keyup', debounce(function(e) { // 代碼 }, 250))
throttling(節流閥)則是另外一種解決問題的方案,它的作法是固定一段時間內函數調用的頻率,它與 debouncing 最大的不一樣之處在於,throttling 會保證至少調用一次。函數
與 debounce
相似,接收兩個參數,一個是須要截流的函數 fn
, 另外一個是函數執行間隔閾值 threshhold
。性能
function throttle(fn, threshhold) { let timer; //定時器 let last; //記錄上次時間 threshhold || (threshhold = 250); //默認間隔爲250ms return function() { // 保存函數調用時的上下文和參數,傳遞給 fn var context = this; var args = arguments; let now = +new Date(); // 若是上次調用距本次調用的時間間隔不夠,則不執行 fn,並從新計時 if(last && now < last + threshhold){ clearTimeout(timer); // 保證在當前時間區間結束後,再執行一次 fn timer = setTimeout({ last = now; fn.apply(context, args); }, threshhold); } else { //若是時間間隔夠了,則馬上執行 fn last = now; fn.apply(context, args); } }
throttle
使用方法以下:this
$(document).on('mouvemove', throttle(function(e) { // 代碼 }, 250))
debouncing 和 throttling 的區別仍是很明顯的:前者把一段時間的屢次調用合併成一次,後者把一段時間的屢次調用減小爲數次。下圖的展現十分便於理解。spa
相關文章:
實例解析防抖動(Debouncing)和節流閥(Throttling)code