JavaScript防抖函數的詳細解析

一、js防抖函數怎麼寫

防抖函數的基本思路是在函數觸發時,設定一個計時器來延遲執行函數,若在延時期間函數被再次觸發,則重新計時,直到延時期滿。這個計時器可以使用setTimeout來實現。具體實現如下所示:

function debounce(func, wait, immediate) {
  let timeout;
  return function() {
    const context = this;
    const args = arguments;
    const callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(function() {
      timeout = null;
      if (!immediate) {
        func.apply(context, args);
      }
    }, wait);
    if (callNow) {
      func.apply(context, args);
    }
  };
}

以上代碼中,debounce函數接收3個參數:需要延遲執行的函數、延遲的毫秒數以及一個布爾值,表示是否在函數被觸發時立即執行函數。返回一個新函數,在調用這個新函數時就會延遲執行傳入的函數。

二、js防抖函數和節流函數的區別

js中的防抖函數和節流函數都是為了解決函數頻繁觸發引起的性能問題,它們的區別在於:

  • 函數節流:一段時間內只能執行一次
  • 函數防抖:只有在上一次觸發函數後的一段時間內沒有再次觸發,才會執行函數

簡單說,函數節流的思路是:以一定時間間隔來執行函數,而函數防抖的思路是:在一定時間段內不允許函數執行,直到時間結束後再執行。

三、js防抖函數立即執行

在前面的js防抖函數中,我們實現的是延遲執行函數,如果要實現立即執行函數,可以根據傳入的第3個參數immediate。當immediate為true時,函數立即執行,當immediate為false或不傳時,函數延遲執行。

 function debounce(func, wait, immediate) {
   let timeout;
   return function() {
     const context = this;
     const args = arguments;
     clearTimeout(timeout);
     if (immediate) {
       const callNow = !timeout;
       timeout = setTimeout(function() {
         timeout = null;
       }, wait);
       if (callNow) {
         func.apply(context, args);
       }
     } else {
       timeout = setTimeout(function() {
         func.apply(context, args);
       }, wait);
     }
   }
 }

四、js按鈕防抖函數

在前端頁面中,按鈕可能會被用戶頻繁的點擊,導致後端介面被頻繁地調用,可能會造成系統崩潰。為了解決這個問題,我們可以使用js防抖函數來實現防止按鈕被頻繁點擊的效果。

function debounceButton(func, wait) {
  let timeout;
  return function() {
    const context = this;
    const args = arguments;
    if (timeout) clearTimeout(timeout);
    const callNow = !timeout;
    timeout = setTimeout(function() {
      timeout = null;
    }, wait);
    if (callNow) {
      func.apply(context, args);
    }
  };
}

以上代碼中的debounceButton函數接收2個參數:需要防抖的函數以及延遲的毫秒數。返回一個新函數,在調用這個新函數時就會延遲執行傳入的函數。

五、js防抖函數不會重置閉包的變數嗎

在防抖的實現中會使用閉包來緩存定時器,那麼就會引起一個問題:閉包中的變數是不是每次調用防抖函數都會被重置?答案是不會。

當我們多次調用防抖函數時,每一個閉包都會持有一份獨立的timeout變數,它們之間是相互獨立的,互不干擾。這就是js閉包的神奇之處。

六、vue防抖函數

在vue中,可以使用官方提供的工具庫lodash來實現防抖函數。在模板裡面可以使用v-debounce指令來調用防抖函數,在後台API請求中就可以避免頻繁地向伺服器請求數據了。

import { debounce } from "lodash";

export default {
  data() {
    return {
      value: ""
    };
  },
  methods: {
    search: debounce(function(query) {
      console.log(query);
    }, 500)
  }
};

七、實現一個防抖函數

以下是一個簡單的防抖函數的代碼實現:

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

此實現中,第一個參數func是需要防抖的函數,delay是防抖時間。返回一個新函數,調用這個新函數時就會延遲執行傳入的函數,若在延時期間函數被再次觸發,則重新計時,直到延時期滿。

八、js防抖寫法

以下是一種簡單的js防抖寫法:

function debounce(fn, wait) {
  return function() {
    clearTimeout(fn.timeoutId);
    fn.timeoutId = setTimeout(() => {
      fn.apply(this, arguments);
    }, wait);
  };
}

在這種寫法中,將timeoutId作為fn函數的一個屬性以緩存定時器。如果在定時器還沒完成時fn又被執行,則清除之前的計時器重新計時。最後執行函數fn。

九、js防抖和節流代碼

以下是一種防抖和節流代碼結合的寫法:

function throttleDebounce(fn, wait1, isDebounce, wait2) {
  let timeoutId, lastExecTime;
  return function() {
    const context = this;
    const args = arguments;
    const elapsedTime = Date.now() - lastExecTime;

    const execFunc = () => {
      lastExecTime = Date.now();
      fn.apply(context, args);
    };

    if (isDebounce) {
      clearTimeout(timeoutId);
      timeoutId = setTimeout(execFunc, wait1);
    } else if (elapsedTime > wait1) {
      execFunc();
    } else {
      clearTimeout(timeoutId);
      timeoutId = setTimeout(execFunc, wait2);
    }
  };
}

在這個函數中,有4個參數:需要防抖或節流的函數,防抖時間,是否是防抖模式,節流時間。返回一個新函數,在調用這個新函數時就會延遲執行或者限流後執行傳入的函數。

十、函數節流和函數防抖選取

在實際開發中,如何選擇函數節流和函數防抖呢?

  • 如果想要限制函數在一定時間段內只被調用一次,則使用函數節流;
  • 如果想要在一段時間內只允許函數執行一次,則使用函數防抖。

舉個例子,如果我們想要執行一個輸入框的驗證,我們可以使用函數防抖,當用戶連續輸入時,不會實時反饋驗證結果,而是在用戶輸入(或停止輸入)一段時間後,才進行驗證。

再舉個例子,當用戶頻繁滾動頁面時,我們可以使用函數節流,每隔一定時間(比如100毫秒)才執行一次處理滾動事件的函數,避免因為這個事件的頻繁觸發導致性能問題。

選擇函數節流還是函數防抖取決於你的場景需求,需要在實際開發中進行權衡取捨。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/249700.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-12 17:12
下一篇 2024-12-12 17:12

相關推薦

  • Python中引入上一級目錄中函數

    Python中經常需要調用其他文件夾中的模塊或函數,其中一個常見的操作是引入上一級目錄中的函數。在此,我們將從多個角度詳細解釋如何在Python中引入上一級目錄的函數。 一、加入環…

    編程 2025-04-29
  • Python中capitalize函數的使用

    在Python的字元串操作中,capitalize函數常常被用到,這個函數可以使字元串中的第一個單詞首字母大寫,其餘字母小寫。在本文中,我們將從以下幾個方面對capitalize函…

    編程 2025-04-29
  • Python中set函數的作用

    Python中set函數是一個有用的數據類型,可以被用於許多編程場景中。在這篇文章中,我們將學習Python中set函數的多個方面,從而深入了解這個函數在Python中的用途。 一…

    編程 2025-04-29
  • 三角函數用英語怎麼說

    三角函數,即三角比函數,是指在一個銳角三角形中某一角的對邊、鄰邊之比。在數學中,三角函數包括正弦、餘弦、正切等,它們在數學、物理、工程和計算機等領域都得到了廣泛的應用。 一、正弦函…

    編程 2025-04-29
  • 單片機列印函數

    單片機列印是指通過串口或並口將一些數據列印到終端設備上。在單片機應用中,列印非常重要。正確的列印數據可以讓我們知道單片機運行的狀態,方便我們進行調試;錯誤的列印數據可以幫助我們快速…

    編程 2025-04-29
  • Python3定義函數參數類型

    Python是一門動態類型語言,不需要在定義變數時顯示的指定變數類型,但是Python3中提供了函數參數類型的聲明功能,在函數定義時明確定義參數類型。在函數的形參後面加上冒號(:)…

    編程 2025-04-29
  • Python實現計算階乘的函數

    本文將介紹如何使用Python定義函數fact(n),計算n的階乘。 一、什麼是階乘 階乘指從1乘到指定數之間所有整數的乘積。如:5! = 5 * 4 * 3 * 2 * 1 = …

    編程 2025-04-29
  • Python定義函數判斷奇偶數

    本文將從多個方面詳細闡述Python定義函數判斷奇偶數的方法,並提供完整的代碼示例。 一、初步了解Python函數 在介紹Python如何定義函數判斷奇偶數之前,我們先來了解一下P…

    編程 2025-04-29
  • Python函數名稱相同參數不同:多態

    Python是一門面向對象的編程語言,它強烈支持多態性 一、什麼是多態多態是面向對象三大特性中的一種,它指的是:相同的函數名稱可以有不同的實現方式。也就是說,不同的對象調用同名方法…

    編程 2025-04-29
  • 分段函數Python

    本文將從以下幾個方面詳細闡述Python中的分段函數,包括函數基本定義、調用示例、圖像繪製、函數優化和應用實例。 一、函數基本定義 分段函數又稱為條件函數,指一條直線段或曲線段,由…

    編程 2025-04-29

發表回復

登錄後才能評論