🚀 一、防抖(debounce)
👉 核心:只执行最后一次
✍️ 基础版
function debounce(fn, delay) {
let timer = null;
return function (...args) {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
}
🔥 进阶版(立即执行 + 可取消)
👉 面试建议写这个
function debounce(fn, delay, immediate = false) {
let timer = null;
function debounced(...args) {
const callNow = immediate && !timer;
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
timer = null;
}, delay);
if (callNow) {
fn.apply(this, args);
}
}
debounced.cancel = function () {
if (timer) {
clearTimeout(timer);
timer = null;
}
};
return debounced;
}
🧠 你要会讲
👉 一句话:
防抖通过不断清除定时器,让函数只在“最后一次触发后”执行。
👉 场景:
- input 搜索
- resize
- 按钮防重复提交
🚀 二、节流(throttle)
👉 核心:单位时间内只执行一次
✍️ 时间戳版(简单)
function throttle(fn, delay) {
let lastTime = 0;
return function (...args) {
const now = Date.now();
if (now - lastTime > delay) {
fn.apply(this, args);
lastTime = now;
}
};
}
✍️ 定时器版
function throttle(fn, delay) {
let timer = null;
return function (...args) {
if (timer) return;
timer = setTimeout(() => {
fn.apply(this, args);
timer = null;
}, delay);
};
}
🔥 高级版(推荐写)
👉 支持“首尾执行”(大厂常问)
function throttle(fn, delay) {
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;
}
fn.apply(this, args);
lastTime = now;
} else if (!timer) {
timer = setTimeout(() => {
fn.apply(this, args);
lastTime = Date.now();
timer = null;
}, remaining);
}
};
}
🧠 你要会讲
👉 一句话:
节流通过控制时间间隔,让函数按固定频率执行。
👉 场景:
- scroll
- 页面拖拽
- mousemove
⚔️ 三、面试必问对比
| 点 | 防抖 | 节流 |
|---|---|---|
| 执行时机 | 最后一次 | 按频率 |
| 是否会丢事件 | 会 | 不会 |
| 适用场景 | 输入框 | 滚动 |
🔥 四、面试加分点(你这个级别必须说)
✅ 1. 本质
都是通过 闭包保存状态 + 定时器控制执行
✅ 2. this 和参数
fn.apply(this, args)
👉 不写这个会被扣分
✅ 3. requestAnimationFrame 节流(高级)
function throttleRAF(fn) {
let lock = false;
return function (...args) {
if (lock) return;
lock = true;
requestAnimationFrame(() => {
fn.apply(this, args);
lock = false;
});
};
}
👉 更适合:
- scroll
- 动画优化