————— --- --- ——————前端
防抖(Debounce)和節流(throttle)都是用來控制某個函數在必定時間內執行多少次的技巧,二者類似而又不一樣。瀏覽器
函數節流(throttle):是讓一個函數沒法在很短的時間間隔內連續調用,當上一次函數執行後過了規定的時間間隔,才能進行下一次該函數的調用。閉包
函數去抖(debounce):讓一個函數在必定間隔內沒有被調用時,纔開始執行被調用方法。
兩個方法都是用來提高前端性能,減輕瀏覽器壓力。app
像防抖仍是很容易想到的,大概意思就是延時處理,而後若是在這段延時內又觸發了事件,則從新開始延時。前端性能
// 簡單示例 window.addEventListener('resize',function(e){ var t; return function(){ if(t) clearTimeout(t); t = setTimeout(function(){ // do something... },500); } }());
爲何要函數節流函數
如下場景每每因爲事件頻繁被觸發,於是頻繁執行DOM操做、資源加載等重行爲,致使UI停頓甚至瀏覽器崩潰。性能
window對象的resize、scroll事件this
拖拽時的mousemove事件spa
射擊遊戲中的mousedown、keydown事件code
文字輸入、自動完成的keyup事件
// 簡單的節流函數 function throttle(func, wait, mustRun) { var timeout, startTime = new Date(); return function() { var context = this, args = arguments, curTime = new Date(); clearTimeout(timeout);
例子以scroll事件進行解析
window.onscroll = function(){ lazyload(); //throttle(lazyload,window); }; function lazyload(){ console.log("scroll執行了"+scrollnum); }
咱們的本意只是讓鼠標滾動一次執行一次滾動函數,可是window的onscroll函數並非等scroll結束以後纔會調用,鼠標滾動或拖動滾動條,就會不停的觸發scroll事件,若是處理的東西多,低版本的IE也會陷入假死狀態。
抖動:若是用手指一直按住一個彈簧,它將不會彈起直到你鬆手爲止。 也就是說當調用動做n毫秒後,纔會執行該動做,若在這n毫秒內又調用此動做則將從新計算執行時間。這種比較適合window的resize事件,實際需求大多爲中止改變大小n毫秒後執行後續處理;而其餘事件大多的需求是以必定的頻率執行後續處理。針對這兩種需求就出現了和throttle兩種解決辦法。
window.onscroll = function(){ //lazyload(); debounce(lazyload,window); }; function debounce(method,context){ clearTimeout(method.timeout); method.timeout = setTimeout(function(){ method.call(context); },500); } function lazyload(){ console.log("scroll執行了"+scrollnum); }
效果以下,能夠看出只執行了一次lazyload函數:
節流以後的滾動一次的執行效果
利用定時器,讓函數執行延遲500毫秒,在500毫秒內若是有函數又被調用則刪除上一次調用,此次調用500毫秒後執行,如此往復
還有一種節流方式,是經過返回閉包的形式,能夠設置延遲時間,二者運行的結果是同樣,可是我在實際操做的時候設置延遲500時,滾動過了一會才執行了,設置爲delay爲100的時候在視覺上就沒有感受延遲。並且函數也只滾動了一次。
function debounce1(method,delay){ var timer = null; return function(){ var context = this,args = arguments; clearTimeout(timer); timer = setTimeout(function(){ method.apply(context,args); },delay); } }
————— --- --- ——————