JavaScript函數節流和函數防抖之間的區別

 

1、概念解釋

 函數節流和函數防抖,二者都是優化高頻率執行js代碼的一種手段。
 你們大概都知道舊款電視機的工做原理,就是一行行得掃描出色彩到屏幕上,而後組成一張張圖片。因爲肉眼只能分辨出必定頻率的變化,當高頻率的掃描,人類是感受不出來的。反而造成一種視覺效果,就是一張圖。就像高速旋轉的風扇,你看不到扇葉,只看到了一個圓同樣。
 同理,能夠類推到js代碼。在必定時間內,代碼執行的次數不必定要很是多。達到必定頻率就足夠了。由於跑得越多,帶來的效果也是同樣。倒不如,把js代碼的執行次數控制在合理的範圍。既能節省瀏覽器CPU資源,又能讓頁面瀏覽更加順暢,不會由於js的執行而發生卡頓。這就是函數節流和函數防抖要作的事。javascript

函數節流是指必定時間內js方法只跑一次。好比人的眨眼睛,就是必定時間內眨一次。這是函數節流最形象的解釋。
函數防抖是指頻繁觸發的狀況下,只有足夠的空閒時間,才執行代碼一次。好比生活中的坐公交,就是必定時間內,若是有人陸續刷卡上車,司機就不會開車。只有別人沒刷卡了,司機纔開車。html

2、函數節流

 函數節流應用的實際場景,多數在監聽頁面元素滾動事件的時候會用到。由於滾動事件,是一個高頻觸發的事件。如下是監聽頁面元素滾動的示例代碼:前端

// 函數節流 var canRun = true; document.getElementById("throttle").onscroll = function(){ if(!canRun){ // 判斷是否已空閒,若是在執行中,則直接return return; } canRun = false; setTimeout(function(){ console.log("函數節流"); canRun = true; }, 300); };

 函數節流的要點是,聲明一個變量當標誌位,記錄當前代碼是否在執行。
 若是空閒,則能夠正常觸發方法執行。
 若是代碼正在執行,則取消此次方法執行,直接returnjava

 這個方法的做用是監聽ID爲throttle元素的滾動事件。
 當canRuntrue,則表明如今的滾動處理事件是空閒的,可使用。
 經過關卡if(!canRun),等於就拿到了通行證。而後下一步的操做就是立馬將關卡關上canRun=false。這樣,其餘請求執行滾動事件的方法,就被擋回去了。
 接着用setTimeout規定最小的時間間隔300,接着再執行setTimeout方法體裏面的內容。
 最後,等setTimeout裏面的方法都執行完畢,才釋放關卡canRun=true,容許下一個訪問者進來。git

 這個函數節流的實現形式,須要注意的是執行的間隔時間是>=300ms。若是具體執行的方法是包含callback的,也能夠將canRun=true這一步放到callback中。理解了函數節流的關卡設置重點,其實改起來就簡單多了。github

3、函數防抖

 函數防抖的應用場景,最多見的就是用戶註冊時候的手機號碼驗證和郵箱驗證了。只有等用戶輸入完畢後,前端才須要檢查格式是否正確,若是不正確,再彈出提示語。如下仍是以頁面元素滾動監聽的例子,來進行解析:瀏覽器

// 函數防抖 var timer = false; document.getElementById("debounce").onscroll = function(){ clearTimeout(timer); // 清除未執行的代碼,重置回初始化狀態 timer = setTimeout(function(){ console.log("函數防抖"); }, 300); }; 

 函數防抖的要點,也是須要一個setTimeout來輔助實現。延遲執行須要跑的代碼。
 若是方法屢次觸發,則把上次記錄的延遲執行代碼用clearTimeout清掉,從新開始。
 若是計時完畢,沒有方法進來訪問觸發,則執行代碼。緩存

 這個方法的做用是監聽ID爲debounce元素的滾動事件
 進入滾動事件方法體的時候,作的第一件事就是清除上次未執行的setTimeout。而setTimeout的引用id由變量timer記錄。
clearTimeout方法,容許傳入無效的值。因此這裏直接執行clearTimeout便可。
 而後,將須要執行的代碼放入setTimeout中,再返回setTimeout引用給timer緩存。
 若是倒計時300ms之後,尚未新的方法觸發滾動事件,則執行setTimeout中的代碼。markdown

 函數防抖的實現重點,就是巧用setTimeout作緩存池,並且能夠輕易地清除待執行的代碼。
 其實,用隊列的方式也能夠作到這種效果。這裏就不深刻了。函數

4、在線demo

函數節流和函數防抖

 這是我寫的一個測試demo,把鼠標移動到模塊上方,滾動滾輪,便可在控制檯查看輸出效果。

demo地址https://wall-wxk.github.io/blogDemo/2017/02/15/throttleAndDebounce.html

閱讀原文http://www.jianshu.com/p/b73c2acad696

相關文章
相關標籤/搜索