面试题 Interview Question
实现一个
throttle
函数,使其保证回调函数在指定的时间间隔内最多只执行一次。
Implement athrottle
function that ensures the callback executes at most once in every specified interval.
要求 Requirements
-
throttle(fn, wait, options)
接收三个参数:fn
:要节流执行的函数
fn
: the function to throttlewait
:等待时间(毫秒)wait
: the interval in millisecondsoptions
(可选):包含{ leading, trailing }
控制首尾执行
options
(optional): an object{ leading, trailing }
to control execution at the start and/or end
-
返回一个新函数:
- 如果
leading: true
,首次调用时立即执行;否则等待首个间隔结束后执行
Ifleading: true
, invoke immediately on the first call; otherwise defer until the first interval ends - 在随后的
wait
毫秒内忽略额外调用
Ignore additional calls during the nextwait
ms - 如果
trailing: true
,在最后一次调用后再执行一次
Iftrailing: true
, invoke one final time after the last call
- 如果
参考答案 Reference Solution
function throttle(fn, wait, options = {}) {
let timer = null;
let lastArgs = null;
const { leading = true, trailing = false } = options;
return function (...args) {
// 立即执行 / Leading execution
if (leading && !timer) {
fn(...args);
} else {
lastArgs = args;
}
// 安排尾调用 / Schedule trailing execution
if (!timer) {
timer = setTimeout(() => {
if (trailing && lastArgs) {
fn(...lastArgs);
lastArgs = null;
}
clearTimeout(timer);
timer = null;
}, wait);
}
};
}
- 纯函数式风格 / Pure FP style:不使用
this
,通过闭包管理定时器和参数。
Pure FP style: nothis
, state managed via closures. - 首尾执行控制 / Leading & Trailing control:
leading
控制首调用,trailing
控制结尾补调用。
leading
controls the first invocation,trailing
controls the final buffered call. - O(1) 时间调用 / O(1) time invocation:所有逻辑仅涉及简单条件判断和
setTimeout
调度,无额外循环或复杂结构。
O(1) time invocation: logic involves only simple checks andsetTimeout
scheduling, with no extra loops or complex structures.
示例 Example
const log = msg => console.log('Logged:', msg);
const throttledLog = throttle(log, 1000, { leading: true, trailing: true });
throttledLog('A'); // → Logged: A (立即执行 / immediate)
throttledLog('B'); // → [ignored] 忽略
throttledLog('C'); // → [ignored] 忽略
// 1000ms 后执行 trailing → Logged: C :contentReference[oaicite:12]{index=12}
考察点 Interview Focus
-
节流 vs 防抖 :理解两者区别及适用场景;Throttling 以固定间隔执行,Debouncing 在停止触发后执行
Throttle vs. Debounce: Understand the differences and when to use each; implement throttling to run at fixed intervals and debouncing to run only after events have stopped firing. -
闭包与计时器管理 :使用闭包保存状态,正确安排和清除
setTimeout
调用
Closures & Timer Management: Use closures to preserve internal state, and properly schedule and clearsetTimeout
calls. -
可配置性设计 :设计
leading
/trailing
选项以满足不同业务需求
Configurable API Design: Provideleading
andtrailing
options to meet different business requirements. -
性能优化 :在高频事件(如
scroll
、resize
、mousemove
)中保持应用流畅性
Performance Optimization: Keep the application smooth during high-frequency events (e.g.,scroll
,resize
,mousemove
). -
边界情况处理 :考虑重复调用、参数转发及异常情况处理等。
Edge Case Handling: Account for repeated invocations, forward parameters correctly, and manage exceptional scenarios.