概念:在事件被触发 n 秒后再执行回调,如果在这 n 秒内又被触发,则重新计时
特点:只执行最后一次
手写防抖:
function debounce(fun, delay) {
let timer = null;
//args将调用函数时传入的所有参数收集为一个数组
return function(...args) {
if (timer) clearTimeout(timer)
timer = setTimeout(() => {
fun.apply(this, args)
}, delay)
}
}概念:规定在一个单位时间内,只能触发一次函数。
特点:按照固定频率执行。
手写节流:
//简化版,通过状态锁
function throttle(fun, delay) {
let run = true
return function(...args) {
if(!run){
return
}
run = false
setTimeout(() => {
fun.apply(this, args)
run = true
}, delay)
}
}| 场景 | 防抖 (Debounce) | 节流 (Throttle) |
| 搜索框输入 (联想查询) | ✅ (等停顿再发请求) | |
| 窗口大小调整 (resize) | ✅ (等调整完再计算) | |
| 表单验证 | ✅ (输完再校验) | |
| 滚动加载 (scroll) | ✅ (每隔200ms判断位置) | |
| 点赞/抢购按钮 (防止连点) | ✅ |
关于防抖节流,必不可少的要讲到闭包
闭包允许一个函数访问并记住其外层作用域的变量,即使外层函数已经执行完毕
闭包的实现依赖于 JavaScript 的两个底层机制:
外部函数中返回了一个内部函数,内部函数引用了外部函数的变量,即使外部函数执行完,变量也不会被销毁,可以继续使用
防抖(Debounce)与 节流(Throttle):利用闭包存储 timer 或 lastTime 标志位。
私有变量封装:模拟类的私有属性,防止外界直接修改内部状态(如:createCounter)。
函数柯里化(Currying):固定一部分参数,返回处理剩余参数的新函数
