手写节流 throttle
代码实现
// 时间戳版:第一次触发立即执行。
function throttle(fn, delay) {
let lastTime = 0;
return function (...args) {
const now = Date.now();
if (now - lastTime >= delay) {
lastTime = now;
fn.apply(this, args);
}
};
}
// 定时器版:第一次触发需要等待 delay 后执行。
function throttleWithTimer(fn, delay) {
let timer = null;
return function (...args) {
if (timer) return;
timer = setTimeout(() => {
timer = null;
fn.apply(this, args);
}, delay);
};
}
笔记记录
手写节流 throttle
是什么
节流的规则是:即使事件一直触发,回调在固定时间内也最多执行一次。
常见场景:
- 滚动时计算页面位置
- 拖拽时更新元素坐标
- 持续点击时限制操作频率
时间戳版
闭包保存上一次执行时间 lastTime。每次触发时,只有当 now - lastTime >= delay 才执行,并更新 lastTime。
触发 -> 计算时间差 -> 未达 delay:忽略
-> 达到 delay:执行,更新 lastTime这个版本的第一次触发会立即执行。
定时器版
闭包保存 timer。没有定时器时就启动一个,已经有定时器时直接忽略新触发;回调执行时把 timer 恢复为 null,让下一个时间窗可以开始。
这个版本的第一次触发会在 delay 毫秒后执行。
代码关键点
- 时间戳版必须在执行时更新
lastTime,否则限频不会生效。 - 当前时间使用
Date.now(),不是Data.now()。 fn.apply(this, args)的第一个参数是this,第二个参数才是参数数组。- 两个实现使用不同函数名,避免后一个函数声明覆盖前一个。