摘要
本文详细讲解前端高频面试与实战核心知识点 ------ 防抖和节流。从概念、原理、区别入手,提供可直接用于生产环境的手写代码,并结合搜索框、滚动加载、窗口 resize、按钮点击等真实业务场景演示用法,帮助你彻底掌握性能优化必备技能。
一、为什么要使用防抖与节流?
在前端开发中,像 scroll、resize、input、mousemove、click 这类事件触发频率极高。如果每次触发都执行复杂逻辑(AJAX、DOM 操作、计算),会严重占用资源,导致页面卡顿、接口请求泛滥。
防抖与节流就是为了控制高频事件的执行次数,做性能优化。
二、防抖(Debounce)
1. 概念
触发高频事件后,延迟 n 秒再执行函数; 如果 n 秒内再次触发,则重新计时。
一句话记忆:**"等你停了,我再执行"**典型场景:搜索框输入联想。
2. 手写基础防抖
javascript
运行
javascript
function debounce(fn, delay = 300) {
let timer = null;
return function (...args) {
// 再次触发时清除上一次定时器
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
}
3. 立即执行版本(可选)
有些场景希望第一次触发立即执行,后续频繁触发不执行:
javascript
运行
javascript
function debounce(fn, delay = 300, immediate = false) {
let timer = null;
return function (...args) {
if (timer) clearTimeout(timer);
// 立即执行
if (immediate && !timer) {
fn.apply(this, args);
}
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
}
4. 防抖适用场景
- 搜索框输入联想(input)
- 表单验证(手机号、邮箱校验)
- 窗口大小变化 resize
- 鼠标移动 mousemove
- 频繁点击按钮防止重复请求
三、节流(Throttle)
1. 概念
高频事件触发时,保证在 n 秒内只执行一次 **。无论触发多快,都按固定频率执行。**
一句话记忆:**"冷却时间,到点才能放技能"**典型场景:滚动加载、下拉刷新。
2. 时间戳版节流(立即执行)
javascript
运行
javascript
function throttle(fn, interval = 300) {
let lastTime = 0;
return function (...args) {
const now = Date.now();
if (now - lastTime >= interval) {
fn.apply(this, args);
lastTime = now;
}
};
}
3. 定时器版节流(延迟执行)
javascript
运行
javascript
function throttle(fn, interval = 300) {
let timer = null;
return function (...args) {
if (!timer) {
timer = setTimeout(() => {
fn.apply(this, args);
timer = null;
}, interval);
}
};
}
4. 节流适用场景
- 滚动加载更多(scroll)
- 高频点击抢购、投票
- 鼠标拖拽、绘图
- 游戏技能冷却
- 视频播放时间更新
四、防抖 vs 节流 核心区别
表格
| 特性 | 防抖 Debounce | 节流 Throttle |
|---|---|---|
| 核心思想 | 最后一次才执行 | 固定频率执行 |
| 执行次数 | 多次触发 → 一次执行 | 多次触发 → 均匀执行 |
| 口诀 | 停了再执行 | 冷却再执行 |
| 典型场景 | 搜索输入、表单校验 | 滚动加载、点击限流 |
一句话区分:
- 防抖:只认最后一次
- 节流:均匀执行
五、真实业务使用示例
1. 搜索框防抖
javascript
运行
javascript
const input = document.querySelector("#search");
input.oninput = debounce(() => {
console.log("发起搜索请求");
}, 500);
2. 滚动节流加载
javascript
运行
javascript
window.onscroll = throttle(() => {
console.log("滚动加载数据");
}, 800);
六、高频面试题
-
**防抖和节流的区别是什么?**答:防抖是多次触发只执行最后一次;节流是在固定时间内只执行一次,均匀限流。
-
**分别适用什么场景?**答:防抖用于输入、resize;节流用于滚动、点击、拖拽。
-
**手写防抖 / 节流要注意什么?**答:保存定时器 / 时间戳、返回闭包、绑定 this、传递参数。
-
**节流时间戳和定时器版本区别?**答:时间戳版立即执行,定时器版延迟执行。
-
**Vue/React 中使用要注意什么?**答:注意防抖节流函数只初始化一次,不要放在 render 内重复生成。
七、工程实践建议
- 搜索输入、表单校验 → 防抖
- 滚动加载、高频点击 → 节流
- 延迟优先 300~500ms
- 项目中可直接使用 Lodash:
_.debounce/_.throttle - 面试必须能手写最简版本
七、总结
- 防抖:高频触发 → 等待停止 → 执行最后一次
- 节流:高频触发 → 固定频率 → 均匀执行
- 防抖适合 "停止后执行",节流适合 "持续触发限流"
- 两者都是前端性能优化必备手段
- 手写核心:闭包保存定时器 / 时间戳,控制执行时机