在開發過程當中會遇到頻率很高的事件或者連續的事件,若是不進行性能的優化,就可能會出現頁面卡頓的現象,好比:git
爲了解決這類問題,經常使用的方法就是throttle(節流)和debounce(去抖)。throttle(節流)和debounce(去抖)都是用來控制某個函數在必定時間內執行多少次的解決方案,二者類似而又不一樣。github
下面就具體的看看二者的類似和區別。ajax
throttle和debounce的做用就是確認事件執行的方式和時機,之前老是不太清楚二者的區別,容易把兩者弄混。閉包
下面就經過兩個簡單的場景描述一下debounce和throttle,之後想到這兩個場景就不會再弄混了:app
debounce 假設你正在乘電梯上樓,當電梯門關閉以前發現有人也要乘電梯,禮貌起見,你會按下開門開關,而後等他進電梯; 若是在電梯門關閉以前,又有人來了,你會繼續開門; 這樣一直進行下去,你可能須要等待幾分鐘,最終沒人進電梯了,纔會關閉電梯門,而後上樓。
因此debounce的做用是,當調用動做觸發一段時間後,纔會執行該動做,若在這段時間間隔內又調用此動做則將從新計算時間間隔。函數
throttle 假設你正在乘電梯上樓,當電梯門關閉以前發現有人也要乘電梯,禮貌起見,你會按下開門開關,而後等他進電梯; 可是,你是個沒耐心的人,你最多隻會等待電梯停留一分鐘; 在這一分鐘內,你會開門讓別人進來,可是過了一分鐘以後,你就會關門,讓電梯上樓。
因此throttle的做用是,預先設定一個執行週期,當調用動做的時刻大於等於執行週期則執行該動做,而後進入下一個新的時間週期。性能
有了上面的瞭解,就能夠去實現簡單debounce和throttle了。優化
首先來看看debounce的實現,根據前面對debounce的描述:this
能夠在Chrome中運行下面的代碼,看看debounce的效果,代碼Github連接:code
var debounce = function(action, delay) { var timer = null; return function() { var self = this, args = arguments; clearTimeout(timer); timer = setTimeout(function() { action.apply(self, args) }, delay); } } // example function resizeHandler() { console.log("resize"); } window.onresize = debounce(resizeHandler, 300);
throttle跟debounce的最大不一樣就是,throttle會有一個閥值,當到達閥值的時候action一定會執行一次。
因此throttle的實現能夠基於前面的debounce的實現,只須要加上一個閥值,代碼Github連接:
var throttleV1 = function(action, delay, mustRunDelay) { var timer = null, startTime; return function() { var self = this, args = arguments, currTime = new Date(); clearTimeout(timer); if(!startTime) { startTime = currTime; } if(currTime - startTime >= mustRunDelay) { action.apply(self, args); startTime = currTime; } else { timer = setTimeout(function() { action.apply(self, args); }, delay); } }; };
其實,對於上面的實現能夠進心簡化,只是經過閉包維護一個開始的時間:
var throttleV2 = function(action, delay){ var statTime = 0; return function() { var currTime = +new Date(); if (currTime - statTime > delay) { action.apply(this, arguments); statTime = currTime ; } } } // example function resizeHandler() { console.log("resize"); } window.onresize = throttleV2(resizeHandler, 300);
經過前面的介紹,應該對debounce和throttle有一個直觀的認識了:
瞭解了throttle和debounce以後,下面看看他們的經常使用場景:
debounce
throttle
對於鍵盤事件,當用戶輸入很是頻繁,可是咱們又必需要在必定時間內(閥值)內執行處理函數的時候,就可使用throttle
對於鼠標移動和窗口滾動,鼠標的移動和窗口的滾動會帶來大量的事件,可是在一段時間內又必須看到頁面的效果