在前端开发中,input 输入、滚动、窗口 resize、点击、鼠标移动...这些高频触发的事件,处理不好,极容易出现:
-
页面卡顿
-
接口狂发
-
浏览器崩溃
-
用户体验极差
所以,防抖(debounce)和节流(throttle)这两个小工具,就变得特别重要。
一句话理解
| 名称 | 核心思想 | 应用场景 |
|---|---|---|
| 防抖 debounce | 多次触发,最后一次生效 | 搜索输入、自动保存 |
| 节流 throttle | 固定时间内只触发一次 | 滚动加载、按钮点击 |
debounce 防抖原理详解
关键:如果事件连续触发,就清除定时器,只有停止触发一段时间后才执行。
手写版 debounce
function debounce(fn, delay) {
let timer = null
return function(...args) {
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
fn.apply(this, args)
}, delay)
}
}
用法示例
window.addEventListener('resize', debounce(() => {
console.log('窗口大小变化完成')
}, 500))
效果:
-
快速 resize -> 不会连续打印
-
停下来 500ms -> 才会触发
throttle 节流原理详解
关键:一段时间内,只允许触发一次
手写版 throttle
function throttle(fn, delay) {
let last = 0
return function(...args) {
const now = Date.now()
if (now - last > delay) {
last = now
fn.apply(this, args)
}
}
}
用法示例
window.addEventListener('scroll', throttle(() => {
console.log('滚动中')
}, 300))
场景实战对比
| 场景 | 用 debounce | 用 throttle |
|---|---|---|
| 搜索框输入 | ✓ | × |
| 滚动监听 | × | ✓ |
| 防止多次点击提交 | × | ✓ |
| 窗口resize | ✓ | × |
| 表单自动保存 | ✓ | × |
手写加强版:支持立即执行的 debounce
有时候希望:
-
输入开始就触发一次(立即执行)
-
然后防抖后再触发
function debounce(fn, delay, 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)
}
}
4962

被折叠的 条评论
为什么被折叠?



