函數防抖是頻繁發生的狀況下,當有足夠的空閒時間,纔會執行代碼一次,是優化高頻率執行代碼的一種手段。實際開發中會遇到頻發觸發事件的狀況,好比 resize
, scroll
, mousemove
事件。html
事件觸發 n 秒後執行,若是在這 n 秒內再次觸發,則以新的事件時間爲準,n 秒後執行。不管觸發多少次,都要等到最後一次觸發 n 秒後才執行。app
用 mousemove
舉例,當鼠標移入時,在 div
內顯示事件函數執行的次數。防抖的簡單實現以下:函數
<div id='container'></div>
let count = 0; let oDiv = document.querySelector('#container'); //防抖函數 function debounce(fn, delay) { let timer; return function() { clearTimeout(timer); timer = setTimeout(fn, delay); } } //事件函數 function eventFn() { oDiv.innerHTML = ++count; } oDiv.onmousemove = debounce(eventFn, 1000);
正常狀況下,在事件函數中使用 this
指向該事件綁定的元素。而此時 eventFn
是做爲定時器的一個參數,this
指向 window
,須要更正 this
指向。優化
function debounce(fn, delay) { let timer; return function() { let _this = this; clearTimeout(timer); timer = setTimeout(function () { fn.apply(_this); }, delay); } }
通常狀況下,事件函數 eventFn
的第一個參數爲 event
對象,但此時,值爲 undefined
。修改防抖函數:this
function debounce(fn, delay) { let timer; return function() { let _this = this; let opt = arguments; clearTimeout(timer); timer = setTimeout(function () { fn.apply(_this, arguments); }, delay); } }
防抖函數中使用了定時器,事件觸發後會延遲必定時間才調用事件函數,有時咱們但願觸發事件能夠當即執行,而後須要 n 秒後才能從新觸發執行。咱們經過傳入第三個參數,判斷是否須要當即執行。code
function debounce(fn, delay, immediate) { let timer; return function() { let _this = this; let opt = arguments; timer && clearTimeout(timer); if(immediate) { let call = !timer; timer = setTimeout(function() { timer = false; }, delay); call && fn.apply(_this, opt); } else { timer = setTimeout(function() { fn.apply(_this, opt); }, delay); } } }