溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

JavaScript函數(shù)節(jié)流和函數(shù)去抖知識點學(xué)習(xí)

發(fā)布時間:2020-09-22 00:03:53 來源:腳本之家 閱讀:102 作者:laozhang 欄目:web開發(fā)

概念

節(jié)流 (throttle) 讓一個函數(shù)不要執(zhí)行的太頻繁,減少執(zhí)行過快的調(diào)用,叫節(jié)流

去抖 (debounce) 去抖就是對于一定時間段的連續(xù)的函數(shù)調(diào)用,只讓其執(zhí)行一次

throttle 應(yīng)用場景

  • DOM 元素的拖拽功能實現(xiàn)(mousemove)
  • 射擊游戲的 mousedown/keydown 事件(單位時間只能發(fā)射一顆子彈)
  • 計算鼠標(biāo)移動的距離(mousemove)
  • Canvas 模擬畫板功能(mousemove
  • 搜索聯(lián)想(keyup
  • 監(jiān)聽滾動事件判斷是否到頁面底部自動加載更多:給 scroll 加了 debounce 后,只有用戶停止?jié)L動后,才會判斷是否到了頁面底部;如果是 throttle 的話,只要頁面滾動就會間隔一段時間判斷一次

debounce 應(yīng)用場景

每次 resize/scroll 觸發(fā)統(tǒng)計事件

文本輸入的驗證(連續(xù)輸入文字后發(fā)送 AJAX 請求進(jìn)行驗證,驗證一次就好)

函數(shù)去抖的實現(xiàn)

我們以scroll事件為例,探究如何是實現(xiàn)滾動一次窗口打印一個hello world 字符串。 如果不對其節(jié)流或者去抖:

window.onscroll = function () {
 console.log('hello world');
}

這樣每滾動一次,實際上會打印多個 hello world。 函數(shù)去抖背后的思路是指,某些代碼不可能在沒有間斷的情況下連續(xù)執(zhí)行。創(chuàng)建一個定時器,在指定的時間間隔之后運行代碼。當(dāng)?shù)诙握{(diào)用該函數(shù)時,它會清除前一次的定時器并設(shè)置另一個。如果前一個定時器已經(jīng)執(zhí)行過了,這個操作就沒有任何意義。然而,如果前一個定時器尚未執(zhí)行,其實就是將其替換為一個新的定時器。目的是只有在執(zhí)行函數(shù)的請求停止了一段時間之后才執(zhí)行。

《高程三》給出了最簡潔最經(jīng)典的去抖代碼,如下:

function debounce(method, context) {
 clearTimeout(method.tId);
 method.tId = setTimeout(function() {
 method.call(context);
 }, 1000);
}

function print() {
 console.log('hello world');
}

window.onscroll = function() {
 debounce(print);
};

再做一些改動

function debounce(delay, action) {
 var tId;
 return function () {
  var context = this;
  var arg = arguments;
  if (tId) clearTimeout(tId);
  tId = setTimeout(function () {
   action.apply(context, arg);
  }, delay);
 }
}

window.onscroll = debounce(1000, print);

函數(shù)節(jié)流的實現(xiàn)

函數(shù)節(jié)流就是讓連續(xù)執(zhí)行的函數(shù),變?yōu)楣潭〞r間段間斷地執(zhí)行。 大概有兩種方式實現(xiàn)。

其一使用時間戳來判斷是否已經(jīng)到回調(diào)執(zhí)行時間,記錄上次執(zhí)行的時間戳,然后每次觸發(fā)事件時執(zhí)行回調(diào),回調(diào)中判斷當(dāng)前時間戳距離上次執(zhí)行時間戳的時間間隔是否有*s,如果是,則執(zhí)行,并更新上次執(zhí)行的時間戳,如此循環(huán)。

var throttle = function(delay, action) {
 var last = 0;
 return function() {
  var curr = new Date();
  if (curr - last > delay) {
   action.apply(this, arguments);
   last = curr;
  }
 }
}

第二種方法是使用定時器,比如,當(dāng)scroll事件剛觸發(fā)時,打印一個hello world ,然后設(shè)置一個1000ms的定時器,此后每次觸發(fā)scroll事件,觸發(fā)回調(diào),如果已經(jīng)存在定時器,則回調(diào)不執(zhí)行方法,知道定時器出發(fā),handler被清除,然后重新設(shè)置定時器。

var throttle = function(delay, action) {
 var timeout;
 var later = function () {
  timeout = setTimeout(function(){
   clearTimeout(timeout);
   // 解除引用
   timeout = null;
  }, delay);
 };
 later();
 if (!timeout) {
  action.apply(this, arguments);
  later();
 }
}

更新方法:

function throttlePro(delay, action) {
 var tId;
 return function () {
  var context = this;
  var arg = arguments;
  if (tId) return;
  tId = setTimeout(function () {
   action.apply(context, arg);
   clearTimeout(tId);
   // setTimeout 返回一個整數(shù),clearTimeout 之后,tId還是那個整數(shù),setInterval同樣如此
   tId = null;
  }, delay);
 }
}

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI