最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript如何利用防抖與節(jié)流優(yōu)化網(wǎng)頁(yè)性能

 更新時(shí)間:2025年08月17日 09:04:07   作者:盛夏綻放  
這篇文章主要為大家詳細(xì)介紹了JavaScript中防抖與節(jié)流的相關(guān)知識(shí),并利用它們進(jìn)行網(wǎng)頁(yè)性能優(yōu)化,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

引言:當(dāng)"狂點(diǎn)族"遇上網(wǎng)頁(yè)性能

想象一下這個(gè)場(chǎng)景:小美正在雙十一搶購(gòu),瘋狂點(diǎn)擊"立即購(gòu)買"按鈕;老王在調(diào)整瀏覽器窗口大小時(shí),頁(yè)面元素不斷重新計(jì)算;小李在搜索框邊輸入邊觸發(fā)搜索…如果沒(méi)有防抖和節(jié)流,這些操作會(huì)讓網(wǎng)頁(yè)像背著10斤重的書包跑步一樣喘不過(guò)氣來(lái)!

電商網(wǎng)站搜索框場(chǎng)景

用戶輸入"最新智能手機(jī)"時(shí):

  • 無(wú)優(yōu)化:觸發(fā)6次搜索請(qǐng)求(每個(gè)字符一次)
  • 防抖:只在停止輸入300ms后觸發(fā)1次
  • 節(jié)流:每200ms最多觸發(fā)1次(可能觸發(fā)3-4次)

沒(méi)有它們會(huì)怎樣?

場(chǎng)景問(wèn)題后果
連續(xù)點(diǎn)擊提交按鈕多次提交表單重復(fù)訂單、服務(wù)器壓力大
窗口頻繁調(diào)整大小持續(xù)觸發(fā)resize事件頁(yè)面卡頓、CPU占用高
輸入框?qū)崟r(shí)搜索每次輸入都請(qǐng)求API請(qǐng)求風(fēng)暴、性能浪費(fèi)

一、防抖(debounce):給"多動(dòng)癥"事件設(shè)置冷靜期

1.1 什么是防抖

“等你說(shuō)完我再行動(dòng)” - 就像電梯關(guān)門按鈕,無(wú)論按多少次,只會(huì)在最后一次操作后等待一段時(shí)間才執(zhí)行。

1.2 實(shí)現(xiàn)代碼(帶詳細(xì)注釋)

模式一:延遲執(zhí)行(經(jīng)典防抖)

/**
 * 經(jīng)典防抖:最后一次觸發(fā)后等待delay毫秒執(zhí)行
 * @param {Function} fn - 目標(biāo)函數(shù)
 * @param {number} delay - 延遲時(shí)間(ms)
 * @returns {Function} - 防抖處理后的函數(shù)
*/
function debounce(fn, delay) {
  // 用于保存定時(shí)器ID的閉包變量
  let timer;

  // 返回一個(gè)包裝后的新函數(shù)
  return function(...args) {
    // 如果已存在定時(shí)器,先清除之前的(避免多次觸發(fā))
    if (timer) clearTimeout(timer);

    // 設(shè)置新的定時(shí)器,在延遲時(shí)間后執(zhí)行原函數(shù)
    timer = setTimeout(() => {
      // 使用apply保持原函數(shù)的this指向和參數(shù)
      fn.apply(this, args);
      // 執(zhí)行后重置定時(shí)器變量(非必須,但有助于垃圾回收)
      timer = null;
    }, delay);
  };
}

模式二:立即執(zhí)行+冷卻

/**
 * 立即執(zhí)行版防抖:首次觸發(fā)立即執(zhí)行,之后進(jìn)入冷卻期
 * @param {Function} fn    - 需要防抖的原始函數(shù)
 * @param {number}  wait   - 冷卻時(shí)間(毫秒)
 * @returns {Function}     - 經(jīng)過(guò)防抖處理的新函數(shù)
 */
function debounceImmediate(fn, wait) {
  // 用于保存定時(shí)器 ID 的閉包變量
  let timer;

  // 返回一個(gè)包裝后的新函數(shù)
  return function (...args) {
    // 如果已經(jīng)有定時(shí)器,先清除(重置冷卻期)
    if (timer) clearTimeout(timer);

    // 判斷是否應(yīng)該立即執(zhí)行
    // 當(dāng) timer 為 null/undefined 時(shí)(即首次觸發(fā)或已冷卻完畢),shouldCallNow 為 true
    const shouldCallNow = !timer;

    // 設(shè)置新的定時(shí)器
    // 定時(shí)器到期后把 timer 置空,表示冷卻期結(jié)束
    timer = setTimeout(() => {
      timer = null;
    }, wait);

    // 如果需要立即執(zhí)行,則立即調(diào)用原函數(shù)
    if (shouldCallNow) {
      fn.apply(this, args);
    }
  };
}

兩種模式對(duì)比表

特性延遲執(zhí)行模式立即執(zhí)行模式
首次觸發(fā)不執(zhí)行立即執(zhí)行
后續(xù)觸發(fā)重置計(jì)時(shí),最后一次執(zhí)行冷卻期內(nèi)不執(zhí)行
執(zhí)行時(shí)機(jī)停止觸發(fā)后delay毫秒首次觸發(fā)立即執(zhí)行
適用場(chǎng)景搜索建議、窗口resize按鈕防重復(fù)點(diǎn)擊、表單提交

1.3 適用場(chǎng)景(表格對(duì)比)

場(chǎng)景不使用防抖使用防抖后
搜索框輸入輸入每個(gè)字符都觸發(fā)搜索停止輸入500ms后才搜索
窗口resize每次像素變化都計(jì)算布局調(diào)整結(jié)束300ms后計(jì)算
按鈕提交快速點(diǎn)擊導(dǎo)致多次提交只認(rèn)最后一次點(diǎn)擊

二、節(jié)流(throttle):給事件加上"技能冷卻時(shí)間"

2.1 什么是節(jié)流

“再著急也得按節(jié)奏來(lái)” - 就像游戲中的技能CD,無(wú)論你按多快,技能都會(huì)按照固定頻率釋放。

2.2 實(shí)現(xiàn)代碼

方式1:定時(shí)器版(尾部執(zhí)行)

/**
 * 定時(shí)器版節(jié)流(保證周期末尾執(zhí)行)
 * @param {Function} fn - 需要節(jié)流的函數(shù)
 * @param {number} wait - 執(zhí)行間隔(ms)
 * @returns {Function} - 節(jié)流處理后的函數(shù)
 */
function throttleByTimer(fn, wait) {
    let timer = null;
    
    return function(...args) {
        const context = this;
        
        if (!timer) {
            timer = setTimeout(() => {
                fn.apply(context, args);
                timer = null;
            }, wait);
        }
    };
}

特點(diǎn)

  • 第一次觸發(fā)后會(huì)等待wait毫秒才執(zhí)行
  • 保證每個(gè)周期末尾會(huì)執(zhí)行一次
  • 停止觸發(fā)后可能還會(huì)執(zhí)行最后一次

執(zhí)行流程

事件觸發(fā): |--x--x---x----x------x---|
執(zhí)行時(shí)機(jī): |----x----x----x----x-----|
           (固定間隔末尾執(zhí)行)

方式2:時(shí)間戳版(頭部執(zhí)行)

/**
 * 時(shí)間戳版節(jié)流(保證周期開(kāi)始執(zhí)行)
 * @param {Function} fn - 需要節(jié)流的函數(shù)
 * @param {number} wait - 執(zhí)行間隔(ms)
 * @returns {Function} - 節(jié)流處理后的函數(shù)
 */
function throttleByTimestamp(fn, wait) {
    let prev = 0; // 上次執(zhí)行時(shí)間戳
    
    return function(...args) {
        const now = Date.now();
        
        if (now - prev >= wait) {
            fn.apply(this, args);
            prev = now;
        }
    };
}

特點(diǎn)

  • 第一次觸發(fā)立即執(zhí)行
  • 保證每個(gè)周期開(kāi)始時(shí)執(zhí)行
  • 停止觸發(fā)后不會(huì)再有額外執(zhí)行

執(zhí)行流程

事件觸發(fā): |--x--x---x----x------x---|
執(zhí)行時(shí)機(jī): |x----x----x----x---------|
           (固定間隔開(kāi)始執(zhí)行)

兩種方式對(duì)比表格

特性定時(shí)器版時(shí)間戳版
首次觸發(fā)延遲執(zhí)行立即執(zhí)行
執(zhí)行時(shí)機(jī)周期末尾周期開(kāi)始
停止觸發(fā)可能執(zhí)行最后一次不會(huì)執(zhí)行最后一次
實(shí)現(xiàn)方式使用setTimeout使用Date.now()
內(nèi)存占用需要維護(hù)timer變量只需維護(hù)prev時(shí)間戳
適用場(chǎng)景需要平滑結(jié)束的操作需要快速響應(yīng)的操作

2.3 防抖與節(jié)流對(duì)比(箭頭圖示)

高頻事件觸發(fā)場(chǎng)景:

      快速連續(xù)觸發(fā)事件
          ↓
防抖:└──────等待期──────┤執(zhí)行最后一次
          ↑ 期間觸發(fā)會(huì)重置等待期
          
節(jié)流:├─執(zhí)行─┼──間隔──┼─執(zhí)行─┤
         固定時(shí)間間隔必執(zhí)行

2.4 適用場(chǎng)景(表格對(duì)比)

場(chǎng)景推薦技術(shù)原因
搜索建議防抖用戶輸入完畢才響應(yīng)
無(wú)限滾動(dòng)節(jié)流定期檢查滾動(dòng)位置
拖拽元素節(jié)流保持流暢的UI更新
窗口resize防抖/節(jié)流防抖(最終布局)/節(jié)流(流暢調(diào)整)

三、防抖與節(jié)流的全方位對(duì)比

3.1 相同之處

共同點(diǎn)說(shuō)明
控制執(zhí)行頻率兩者都能減少高頻事件的觸發(fā)次數(shù)
提升性能有效降低CPU使用率、減少不必要的函數(shù)調(diào)用
閉包應(yīng)用都利用閉包保存狀態(tài)(timer/lastTime)
返回新函數(shù)都是高階函數(shù),返回包裝后的函數(shù)

3.2 核心區(qū)別

特性防抖(debounce)節(jié)流(throttle)
執(zhí)行時(shí)機(jī)最后一次觸發(fā)后延遲執(zhí)行固定間隔執(zhí)行
重置機(jī)制新觸發(fā)會(huì)重置計(jì)時(shí)新觸發(fā)不影響既定節(jié)奏
保證執(zhí)行快速連續(xù)觸發(fā)時(shí)可能永不執(zhí)行必定會(huì)按節(jié)奏執(zhí)行
內(nèi)存占用需要維護(hù)單個(gè)timer需要維護(hù)timer+lastTime
適用場(chǎng)景關(guān)注最終狀態(tài)(如搜索)關(guān)注過(guò)程狀態(tài)(如滾動(dòng))

四、性能優(yōu)化數(shù)據(jù)對(duì)比

通過(guò)Chrome DevTools測(cè)試相同場(chǎng)景:

操作原生事件防抖處理節(jié)流處理
輸入100個(gè)字符100次調(diào)用1次調(diào)用20次調(diào)用(每5字符)
持續(xù)滾動(dòng)10秒500+次調(diào)用1次調(diào)用10次調(diào)用(每秒1次)
CPU占用峰值85%15%30%

結(jié)語(yǔ):成為性能優(yōu)化大師

防抖和節(jié)流就像前端開(kāi)發(fā)中的"呼吸法":

  • 防抖是深呼氣后的暫停(等待穩(wěn)定)
  • 節(jié)流是均勻的腹式呼吸(保持節(jié)奏)

記住這個(gè)開(kāi)發(fā)者口訣:

“高頻事件要優(yōu)化,防抖節(jié)流來(lái)幫忙;
輸入搜索用防抖,滾動(dòng)動(dòng)畫節(jié)流上;
參數(shù)調(diào)優(yōu)看場(chǎng)景,組合使用更健康!”

現(xiàn)在,打開(kāi)你的開(kāi)發(fā)者工具,找到那些"氣喘吁吁"的事件處理器,用合適的策略給它們裝上"呼吸調(diào)節(jié)器"吧! 

到此這篇關(guān)于JavaScript如何利用防抖與節(jié)流優(yōu)化網(wǎng)頁(yè)性能的文章就介紹到這了,更多相關(guān)JavaScript防抖與節(jié)流內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

尼勒克县| 桂阳县| 铜山县| 楚雄市| 田林县| 娱乐| 诸城市| 莒南县| 桦南县| 榆中县| 科技| 山阴县| 淮南市| 福州市| 青海省| 木里| 宁城县| 泽普县| 平南县| 鸡东县| 宁晋县| 永川市| 五台县| 黔东| 故城县| 正阳县| 湘阴县| 油尖旺区| 崇礼县| 遵义县| 武山县| 邢台市| 同江市| 南丰县| 凌云县| 浮梁县| 肥西县| 揭东县| 西充县| 邹平县| 常熟市|