JS防抖與節流教學

滾動、視窗縮放、鍵盤輸入這類高頻事件,若直接把處理函式綁上去,瀏覽器很快就會喘不過氣。防抖(Debouncing)和節流(Throttling)是兩種常見的解法,差別在於「事件停了才執行」還是「固定間隔最多執行一次」,選錯方向效果會差很多。

防抖 (Debouncing)

觸發事件後,等待指定時間才執行處理函式。如果等待期間又觸發了,就重新計時。連續快速觸發的情況下,最終只會執行一次。

使用時機

觸發頻率高、但不需要即時響應每次觸發的場景:

  • 搜尋框輸入(使用者停止輸入後再發出請求)
  • 視窗大小調整(調整結束後再重新計算排版)

範例

1
2
3
4
5
6
7
8
9
10
11
12
13
function debounce(func, wait) {
let timeout;
return function(...args) {
const context = this;
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(context, args), wait);
};
}

// 使用防抖
window.addEventListener('resize', debounce(function() {
console.log('視窗大小調整完成');
}, 500));

節流 (Throttling)

在指定時間內最多只執行一次處理函式。不管這段期間觸發了幾次事件,執行次數都受到控制。

使用時機

需要穩定控制事件處理頻率的場景:

  • 滾動事件(例如無限滾動的載入更多)
  • 遊戲中的按鍵響應

範例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function throttle(func, wait) {
let lastTime = 0;
return function(...args) {
const now = new Date().getTime();
if (now - lastTime > wait) {
lastTime = now;
func.apply(this, args);
}
};
}

// 使用節流
window.addEventListener('scroll', throttle(function() {
console.log('滾動事件被觸發');
}, 1000));

結論

兩者的核心差異:防抖是「事件平靜下來之後才動」,節流是「不管觸發幾次,固定間隔最多動一次」。搜尋框用防抖、無限滾動用節流,選對了才有實際效果。