技術分享:函式節流和防抖
其原理是用時間戳來判斷是否已到回撥該執行時間,記錄上次執行的時間戳,然後每次觸發 scroll 事件執行回撥,回撥中判斷當前時間戳距離上次執行時間戳的間隔是否已經到達 規定時間段,如果是,則執行,並更新上次執行的時間戳,如此迴圈。
html, body { height: 500%; // 讓其出現滾動條}
function throttle(fn, delay) { // 記錄上一次函式觸發的時間 var lastTime = 0; return function() { // 記錄當前函式觸發的時間 var nowTime = Date.now(); if (nowTime - lastTime delay) { // 修正this指向問題 fn.call(this); // 同步時間 lastTime = nowTime; } }}document.onscroll = throttle(function() { console.log('scroll事件被觸發了' + Date.now()) }, 200)
上例中用到了閉包的特性–可以使變數lastTime的值長期儲存在記憶體中。
2.函式節流的應用場景
需要間隔一定時間觸發回撥來控制函式呼叫頻率:
DOM 元素的拖拽功能實現(mousemove)
搜尋聯想(keyup)
計算滑鼠移動的距離(mousemove)
Canvas 模擬畫板功能(mousemove)
射擊遊戲的 mousedown/keydown 事件(單位時間只能發射一顆子彈)
監聽滾動事件判斷是否到頁面底部自動載入更多:給 scroll 加了 debounce 後,只有使用者停止滾動後,才會判斷是否到了頁面底部;如果是 throttle 的話,只要頁面滾動就會間隔一段時間判斷一次二、函式防抖(debounce)
防抖函式:一個需要頻繁觸發的函式,在規定時間內,只讓最後一次生效,前面的不生效。
1.如何實現
其原理就第一次呼叫函式,建立一個定時器,在指定的時間間隔之後執行程式碼。當第二次呼叫該函式時,它會清除前一次的定時器並設定另一個。如果前一個定時器已經執行過了,這個操作就沒有任何意義。然而,如果前一個定時器尚未執行,其實就是將其替換為一個新的定時器,然後延遲一定時間再執行。
button id='btn'按鈕/buttonscript type=text/javascriptfunction debounce(fn, delay) { // 記錄上一次的延時器 var timer = null; return function() { // 清除上一次延時器 clearTimeout(timer) timer = setTimeout(function() { fn.apply(this) }, delay) }}document.getElementById('btn'). = debounce(function() { console.log('點選事件被觸發' + Date.now())}, 1000)/script
上例中也用到了閉包的特性–可以使變數timer的值長期儲存在記憶體中。
2.函式防抖的應用場景
對於連續的事件響應我們只需要執行一次回撥:
每次 resize/scroll 觸發統計事件
文字輸入的驗證(連續輸入文字後傳送 AJAX 請求進行驗證,驗證一次就好)三、總結
函式節流和函式去抖的核心其實就是限制某一個方法被頻繁觸發,而一個方法之所以會被頻繁觸發,大多數情況下是因為 DOM 事件的監聽回撥,而這也是函式節流以及防抖多數情況下的應用場景。