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

來源:互聯網
上載者:User

標籤:延遲   郵箱   cimage   div   deb   掃描   run   模組   代碼執行   

一、概念解釋

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

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

二、函數節流

?函數節流應用的實際情境,多數在監聽頁面元素滾動事件的時候會用到。因為滾動事件,是一個高頻觸發的事件。以下是監聽頁面元素滾動的範例程式碼:

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

?函數節流的要點是,聲明一個變數當標誌位,記錄當前代碼是否在執行。
?如果空閑,則可以正常觸發方法執行。
?如果代碼正在執行,則取消這次方法執行,直接return

?這個方法的作用是監聽ID為throttle元素的滾動事件。
?當canRuntrue,則代表現在的滾動處理事件是閒置,可以使用。
?通過關卡if(!canRun),等於就拿到了通行證。然後下一步的操作就是立馬將關卡關上canRun=false。這樣,其他請求執行滾動事件的方法,就被擋回去了。
?接著用setTimeout規定最小的時間間隔300,接著再執行setTimeout方法體裡面的內容。
?最後,等setTimeout裡面的方法都執行完畢,才釋放關卡canRun=true,允許下一個訪問者進來。

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

三、函數防抖

?函數防抖的應用情境,最常見的就是使用者註冊時候的手機號碼驗證和郵箱驗證了。只有等使用者輸入完畢後,前端才需要檢查格式是否正確,如果不正確,再彈出提示。以下還是以頁面元素滾動監聽的例子,來進行解析:

// 函數防抖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中的代碼。

?函數防抖的實現重點,就是巧用setTimeout做緩衝池,而且可以輕易地清除待執行的代碼。
?其實,用隊列的方式也可以做到這種效果。這裡就不深入了。

四、線上demo

?這是我寫的一個測試demo,把滑鼠移動到模組上方,滾動滾輪,即可在控制台查看輸出效果。

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

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

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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.