FE Interview Hub
Web Vitals中階

什麼是節流 (throttle)?如何實踐節流 (throttle) 函式?

AI 練習作答

什麼是 Throttle(節流)?

節流:當事件被高頻觸發時,固定每 N 毫秒最多執行一次。無論期間被觸發多少次,在間隔時間內都只會執行一次。

核心精神:固定節奏、限流執行

常見應用情境

  • scroll 事件(無限滾動、滾動視差、回頂按鈕顯示)
  • mousemove 事件(拖曳、追蹤滑鼠)
  • 遊戲中的射擊、攻擊 cooldown
  • 視窗 resize(若要即時反應但限流)

實作方式一:時間戳版(leading)

第一次會立刻執行,後續每 delay 才再執行一次。

function throttle(fn, delay = 300) {
  let lastTime = 0;

  return function (...args) {
    const now = Date.now();

    if (now - lastTime >= delay) {
      fn.apply(this, args);
      lastTime = now;
    }
  };
}

實作方式二:計時器版(trailing)

第一次不執行,等待 delay 過後才執行,結束後再開新一輪。

function throttle(fn, delay = 300) {
  let timer = null;

  return function (...args) {
    if (timer) return;

    timer = setTimeout(() => {
      fn.apply(this, args);
      timer = null;
    }, delay);
  };
}

實作方式三:雙劍合璧(leading + trailing)

結合時間戳與計時器:第一次立刻執行,最後一次也會補執行。

function throttle(fn, delay = 300) {
  let lastTime = 0;
  let timer = null;

  return function (...args) {
    const now = Date.now();
    const remaining = delay - (now - lastTime);

    if (remaining <= 0) {
      // 時間已到,立刻執行
      if (timer) {
        clearTimeout(timer);
        timer = null;
      }
      lastTime = now;
      fn.apply(this, args);
    } else if (!timer) {
      // 安排最後一次補執行
      timer = setTimeout(() => {
        lastTime = Date.now();
        timer = null;
        fn.apply(this, args);
      }, remaining);
    }
  };
}

使用範例

const onScroll = throttle(() => {
  console.log('scrollY:', window.scrollY);
}, 200);

window.addEventListener('scroll', onScroll);

實作細節

  • 時間戳版:首次立即執行,但最後一次可能被丟掉。
  • 計時器版:最後一次一定執行,但首次會延遲 delay 毫秒。
  • 雙劍版:兩者優點兼具,接近 lodash _.throttle 的行為。
  • 記得以 fn.apply(this, args) 保留呼叫者上下文。

Debounce vs Throttle

比較 Throttle Debounce
策略 固定頻率執行 停下來後才執行
類比 水龍頭固定滴水 電梯等最後一個人
適用 scroll、mousemove、遊戲 cooldown 搜尋、resize、輸入驗證

✦ AI 模擬面試

輸入你的答案,AI 即時分析精準度與改進空間

登入後即可使用 AI 評分