Web Vitals中階
什麼是節流 (throttle)?如何實踐節流 (throttle) 函式?
什麼是 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 評分
