博客 / 詳情

返回

前端性能優化的利器 ——— 淺談JavaScript中的防抖和節流

防抖和節流函數是工作中兩種常用的前端性能優化函數,今天我就來總結一下什麼是防抖和節流,並詳細説明一下如何在工作中應用防抖和節流函數

什麼是防抖和節流?

在 JavaScript 中,防抖(debounce)和節流(throttle)是用來限制函數執行頻率的兩種常見技術。

防抖(debounce) 是指在某個時間段內,只執行最後一次觸發的函數調用。如果在這個時間段內再次觸發該函數,會重新計時,直到等待時間結束才會執行函數。
這個技術通常用於處理頻繁觸發的事件,比如窗口大小調整、搜索框輸入等。防抖可以避免函數執行過多次,以減少網絡開銷和性能負擔。

節流(throttle) 是指在一段時間內限制函數的執行頻率,保證一定時間內只執行一次函數調用。無論觸發頻率多高,都會在指定時間間隔內執行一次函數。
這個技術通常用於處理連續觸發的事件,比如滾動事件、鼠標移動事件等。節流可以控制函數的執行頻率,以減少資源消耗和提高性能。

手寫一個防抖的工具函數

function debounce(func, delay) {
  let timeoutId;
  
  return function() {
    const context = this;
    const args = arguments;
    
    clearTimeout(timeoutId);
    
    timeoutId = setTimeout(function() {
      func.apply(context, args);
    }, delay);
  };
}

函數説明

  1. 這個防抖函數接受兩個參數:func表示需要進行防抖的函數,delay表示延遲的時間間隔(以毫秒為單位)
  2. 函數內部使用了一個timeoutId變量來保存定時器的標識。當調用防抖函數返回的新函數時,會清除之前的定時器,並設置一個新的定時器。只有在延遲時間內沒有再次調用該新函數時,才會觸發最終的函數執行

使用示例

該示例表示在全局滾動事件中使用防抖函數,每200毫秒內如果觸發滾動事件,那麼不會執行handleScroll()函數。
然後重新計時200毫秒,再次判斷,直到最後一個200毫秒內沒有觸發滾動事件,才會執行handleScroll()函數

function handleScroll() {
  console.log('Scrolled');
}
const debouncedScroll = debounce(handleScroll, 200);
window.addEventListener('scroll', debouncedScroll);

手寫一個節流的工具函數

function throttle(func, delay) {
  let timeoutId;
  let lastExecTime = 0;

  return function(...args) {
    const currentTime = Date.now();
    const remainingTime = delay - (currentTime - lastExecTime);

    clearTimeout(timeoutId);

    if (remainingTime <= 0) {
      func.apply(this, args);
      lastExecTime = currentTime;
    } else {
      timeoutId = setTimeout(() => {
        func.apply(this, args);
        lastExecTime = Date.now();
      }, remainingTime);
    }
  };
}

函數説明

  1. 這個節流函數接受兩個參數:func是要執行的函數,delay是延遲時間(以毫秒為單位)
  2. 它返回一個新的函數,該函數在調用時會根據指定的延遲時間來限制原始函數的執行頻率

使用示例

在全局滾動事件中使用節流函數,無論在滾動事件的監聽過程中,觸發了幾次handleScroll()函數,都只會在每200毫秒內執行一次handleScroll()函數。

function handleScroll() {
  console.log('Scrolled');
}
const throttledScroll = throttle(handleScroll, 200);
window.addEventListener('scroll', throttledScroll);

如何在工作中應用防抖和節流

防抖和節流主要應用於:搜索框輸入事件監聽、窗口大小調整事件監聽、按鈕點擊事件監聽、滾動事件監聽、鼠標移動事件監聽等等場景。

工作中哪些場景可以使用防抖函數?

  1. 用户輸入: 當用户在表單輸入框中頻繁輸入時,可以使用防抖函數來延遲處理用户輸入,避免頻繁的請求或操作,提高性能和用户體驗。
  2. 搜索框: 在搜索框中,當用户連續輸入關鍵字時,可以使用防抖函數來延遲發送搜索請求,以避免請求過多。
  3. 窗口調整: 當窗口大小調整時,會觸發resize事件,可以使用防抖函數來限制resize事件的觸發次數,避免頻繁執行調整相關的代碼。
  4. 按鈕頻繁點擊: 當按鈕被頻繁點擊時,可以使用防抖函數來限制按鈕點擊的觸發次數。

工作中哪些場景可以使用節流函數?

  1. 用户輸入: 當用户在文本框中輸入時,觸發搜索功能。使用節流函數可以限制搜索請求的頻率,以避免頻繁的網絡請求。例如,可以設置一個定時器,在用户輸入後的一小段時間內不觸發搜索請求,只在定時器結束後才進行搜索。
  2. 無限加載: 當用户滾動頁面時,觸發加載更多數據的操作。使用節流函數可以限制加載操作的頻率,以提高頁面的響應性能。例如,可以設置一個定時器,在用户滾動過程中只觸發加載操作的最後一次滾動事件。
  3. 按鈕頻繁點擊: 當用户頻繁點擊某個按鈕時,觸發某個操作。使用節流函數可以限制點擊操作的頻率,以避免重複操作或者混亂的界面狀態。例如,可以設置一個定時器,在用户點擊後的一小段時間內不觸發重複操作。

如何使用loadsh.js工具庫中的防抖和節流函數

實際開發過程中,我們的項目中可能會直接使用loadsh.js工具庫,來避免重複造輪子,所以這裏也特地説明一下如何使用loadsh.js工具庫中的防抖和節流函數

  1. 安裝loadsh.js工具庫

    npm install lodash  
  2. 在項目中引入loadsh.js工具庫,不同前端項目引入方式不同,請自行鑑別

    import { debounce, throttle } from 'loadsh';
  3. 使用防抖函數,該示例中,submitData()函數被限制為每1秒只會執行最後一次,如果在等待時間內多次調用該函數,則會重置1秒的等待時間

    // 定義要延遲執行的函數
    function submitData(data) {
      console.log('保存數據:', data);
    }
    
    // 使用debounce函數創建一個延遲執行的函數
    const debouncedFn = _.debounce(submitData, 1000);
    
    // 模擬連續觸發保存數據的操作
    // 等待1秒後,只會執行最後一次保存數據的操作
    debouncedFn('數據1'); // 不會輸出
    debouncedFn('數據2'); // 不會輸出
    debouncedFn('數據3'); //  輸出 —— 保存數據:數據3
    
  4. 使用節流函數,該示例中,throttledFn()函數被限制為每秒只能執行一次,如果在等待時間內多次調用該函數,則不會執行

    // 定義要減少調用次數的函數
    function fetchData(data) {
     console.log('拉取數據:', data);
    }
    
    // 使用throttle函數創建一個定時執行的函數
    const throttledFn = _.throttle(fetchData, 2000);
    
    // 調用throttledFn函數
    throttledFn('數據1'); // 輸出 —— 拉取數據: 數據1
    
    // 在1秒內多次調用throttledFn函數
    throttledFn('數據2'); // 不會輸出
    
    // 2秒後再次調用throttledFn函數
    setTimeout(() => {
      throttledFn('數據3'); // 輸出 —— 拉取數據: 數據3
    }, 1000);

我是 fx67ll.com,如果您發現本文有什麼錯誤,歡迎在評論區討論指正,感謝您的閲讀!
如果您喜歡這篇文章,歡迎訪問我的 本文github倉庫地址,為我點一顆Star,Thanks~ :)
轉發請註明參考文章地址,非常感謝!!!

user avatar zzd41 頭像 1023 頭像 hightopo 頭像 user_p5fejtxs 頭像 joytime 頭像 mrqueue 頭像 icezero 頭像 beilee 頭像 william_wang_5f4c69a02c77b 頭像 huaihuaidedianti 頭像 mouyi_63f6f68ba66d9 頭像 513928731 頭像
23 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.