这是一道 Salesforce 前端面试中出现的 JavaScript 基础实现题。面试记录显示,这一轮明确属于 Frontend 面试,并允许候选人使用 JavaScript 或 TypeScript 作答。
Implement debounce in JS.
实现一个 debounce 函数。
当一个函数在短时间内被连续调用时,不要每次都立即执行,而是在停止调用一段时间后,只执行最后一次。
const handleSearch = debounce((keyword) => {
console.log("Searching:", keyword);
}, 300);
handleSearch("s");
handleSearch("sa");
handleSearch("sal");
handleSearch("salesforce");上面的调用发生在很短的时间内,最终只会执行一次:
Searching: salesforcefunction debounce(fn, delay) {
let timer = null;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
}使用方式
const debouncedSearch = debounce(function (keyword) {
console.log("Search:", keyword);
}, 500);
debouncedSearch("Sales");
debouncedSearch("Salesforce");每次调用返回函数时,都会先清除之前的定时器,再创建新的定时器。
只有在连续 500ms 没有新的调用后,原函数才会真正执行。
为什么要使用 apply
下面这种写法虽然简单:
setTimeout(() => {
fn(...args);
}, delay);但更完整的实现通常会写成:
fn.apply(this, args);这样可以保留函数调用时的 this。
例如:
const user = {
name: "Salesforce",
printName: debounce(function () {
console.log(this.name);
}, 300),
};
user.printName();输出:
Salesforce如果错误地丢失了 this,输出可能会变成 undefined。
面试官继续追问
- 如何保留参数和
this? - 如何增加
cancel方法? - 如何实现第一次立即执行?
- 如何同时支持 leading 和 trailing?
- debounce 和 throttle 有什么区别?
- React 中使用 debounce 时需要注意什么?
- 组件卸载时如何取消未执行的定时器?
在 React 中,常见问题是每次渲染都重新创建 debounced 函数:
function Search() {
const handleSearch = debounce((value) => {
console.log(value);
}, 300);
}更合理的方式是使用 useMemo 或 useCallback 保持函数引用稳定,并在组件卸载时调用 cancel。
这道题代码量不大,主要考察:
- 对闭包的理解
setTimeout和clearTimeout- 参数透传
this绑定- 边界情况处理
- 是否能够根据追问扩展功能
面试时可以先完成基础 trailing debounce,再主动说明可以继续支持 cancel、立即执行以及 TypeScript 类型。相比一开始就写非常复杂的版本,这样更容易保证正确性。
CSOAHelp 提供北美大厂面试实时文本辅助与 Mock Interview 服务,覆盖前端、全栈、算法和系统设计面试。
我们也有代面试,面试辅助,OA代写等服务助您早日上岸~

