下面是 第 18 题:防抖(debounce)和节流(throttle)
依旧:详细版 + 手写实现 + 场景 + 速记卡
✅ 第 18 题:防抖和节流是什么?区别是什么?如何实现?
📘 一、前端为什么需要防抖节流?
前端有很多高频触发事件:
- input 输入
- scroll 滚动
- resize 窗口尺寸变化
- mousemove 鼠标移动
- keyup/keyDown
如果不控制频率,会导致:
- 性能下降
- 请求过多
- 渲染抖动
防抖和节流就是为了解决这个问题。
📘 二、防抖(Debounce)
🧠 机制:
事件触发后等待 n ms,如果期间又触发,则重新计时。只有最后一次触发才执行。
使用场景:
- 关键字搜索(用户停止输入才发请求)
- 调整窗口大小(结束调整再计算)
- 文本输入校验
🧪 示例:
用户连续输入:a → ab → abc
等待 300ms,不再输入 → 执行一次请求。
✍️ 手写防抖(立即执行可选)
ini
function debounce(fn, delay, immediate = false) {
let timer = null;
return function(...args) {
const context = this;
if (timer) clearTimeout(timer);
if (immediate && !timer) {
fn.apply(context, args);
}
timer = setTimeout(() => {
if (!immediate) fn.apply(context, args);
timer = null;
}, delay);
};
}
📘 三、节流(Throttle)
🧠 机制:
无论事件触发多少次,每隔 n ms 只执行一次。
使用场景:
- 页面滚动,触发统计(每 200ms 记录一次位置)
- 按钮连续点击(防止疯狂点击)
- 悬停拖拽 mousemove 事件
🧪 示例:
持续滚动:
0ms → 执行
100ms → 忽略
200ms → 执行
300ms → 忽略
...
✍️ 手写节流(时间戳版)
ini
function throttle(fn, delay) {
let last = 0;
return function(...args) {
const now = Date.now();
if (now - last > delay) {
fn.apply(this, args);
last = now;
}
};
}
✍️ 另一版(定时器版)
ini
function throttle(fn, delay) {
let timer = null;
return function(...args) {
if (!timer) {
timer = setTimeout(() => {
fn.apply(this, args);
timer = null;
}, delay);
}
};
}
📘 四、区别总结(必背)
| 特性 | 防抖 Debounce | 节流 Throttle |
|---|---|---|
| 执行次数 | 只执行 最后一次 | 按固定间隔执行 |
| 应用场景 | 输入框搜索、窗口调整 | scroll、mousemove、抢购按钮 |
| 高频触发 | 不执行 | 间隔执行 |
| 核心思路 | 等一等 | 降速执行 |
📘 五、速记卡片(10 秒版)
arduino
防抖:最后一次 ------ 停下来我再执行(搜索框)
节流:固定频率 ------ 你再急也按节奏来(scroll)
防抖用 setTimeout,触发就清空重新计时
节流用时间戳或定时器,不到时间不执行
要继续下一题吗?
第 19 题:前端常见渲染机制(重排 + 重绘 + 浏览器渲染流水线)