文章

前端面試手寫練習 - debounce (進階)

文章發表於

問題

debounce (進階) 與 throttle (進階) 都是要多了一個 option 參數,這個參數包含了 leadingtrailing 兩個屬性,分別代表是否要執行第一次與最後一次的事件。

debounce(func, [(wait = 0)], [(option = { leading: false, trailing: true })];
  • func:要防抖動的事件函式
  • wait:延遲時間,單位為毫秒
  • option:選項物件,包含 leadingtrailing 兩個屬性,分別代表是否要執行第一次與最後一次的事件

示意圖

原始事件流 (每 ─ 代表 1s)

─ A ─ B ─ C ─ ─ D ─ ─ ─ ─ ─ ─ E ─ ─ F ─ G ─ ─ ─

leading: false 以及 trailing: true

─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ D ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ G

leading: true 以及 trailing: false

─ A ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ E ─ ─ ─ ─ ─ ─ ─ ─ ─

leading: true 以及 trailing: true

─ A ─ ─ ─ ─ ─ D ─ ─ ─ ─ ─ ─ E ─ ─ ─ ─ ─ ─ ─ ─ G

練習區

在了解問題後,可以嘗試先寫下您的思路,再到下方的練習區域實際寫出程式碼。

import { add } from './add';

describe('add', () => {
  test('Commutative Law of Addition', () => {
    expect(add(1, 2)).toBe(add(2, 1));
  });
});

Open browser consoleTests

筆者思路

  1. debounce (進階) 與先前的 debounce 函式非常相似,而這次只是多了 option 參數。
  2. leadingtrue 時,我們需要在 debounce 函式中先執行一次 func。反之要將最後一次的參數儲存起來,在 timeout 結束執行 func 時使用。
  3. 在 timeout 結束後並當 trailingtrue 時,再次執行 func

筆者解答

function debounce(func, wait, option = { leading: false, trailing: true }) {
let timerId = null
let lastArgs = null
return function (...args) {
if (timerId) {
clearTimeout(timerId)
}
if (option.leading && !timerId) {
func.apply(this, args)
} else {
lastArgs = args
}
timerId = setTimeout(() => {
if (option.trailing && lastArgs) {
func.apply(this, lastArgs)
}
timerId = null
lastArgs = null
}, wait)
}
}

相關題目

  1. bigfrontend.dev - debounce with leading & trailing option

延伸閱讀

  1. Debounce vs Throttle: Definitive Visual Guide
如果您喜歡這篇文章,請點擊下方按鈕分享給更多人,這將是對筆者創作的最大支持和鼓勵。