有一些瀏覽器事件能夠在很短的事件內快速觸發屢次,例如 調整窗口大小 或 向下滾動 頁面。例如,若是將事件監聽器綁定到窗口滾動事件上,而且用戶繼續很是快速地向下滾動頁面,你的事件可能會在3秒的範圍內被觸發數千次。這可能會致使一些嚴重的性能問題,面試
若是在面試中討論構建應用程序和事件,如滾動、窗口調整大小,或鍵盤按下的事件時,必定要說起函數防抖動和函數節流來提高頁面速度和性能。瀏覽器
直接綁定函數到scroll事件是很是錯誤的決定,當用戶滾動頁面時,頁面可能會變得很是慢甚至未響應。而函數防抖和函數節流是解決這個問題的一種方式,經過限制須要通過的事件,直至再次調用函數,在處理一些高頻率觸發的 DOM 事件的時候,它們都能極大提升用戶體驗。閉包
若是一個事件被頻繁觸發屢次,而且觸發的時間間隔太短,則防抖函數可使得對應的事件處理函數只執行一次app
// debounce函數用來包裹咱們的事件處理方法 function debounce(fn, delay){ // 持久化一個定時器 let timer = null // 閉包函數能夠訪問timer return function(){ // 經過 this 和 arguments 得到函數的做用域和參數 let context = this let args = arguments // 若是事件被觸發,清除timer並從新開始計時 clearTimeout(timer) timer = setTimeout(function() { fn.apply(context, args) }, delay) } } function foo(){ console.log('You are scrolling!') } document.addEventListener('scroll', debounce(foo, 50));
throttle 的概念理解稍微容易一些,若是一個事件被頻繁觸發屢次,節流函數能夠按照固定頻率去執行對應的事件處理方法函數
function throttle(fn, threshold){ var last var timer threshold || (threshold = 250) return function(){ let context = this let args = arguments var now = +new Date() if(last&&now<last+threshold){ clearTimeout(timer) timer = setTimeout(function(){ last = now fn.apply(context, args) },threshold) }else { last = now fn.apply(context, args) } } }