节流是控制高频事件执行频率的手段,确保函数在指定时间间隔内最多执行一次;其核心是固定间隔只执行一次,通过记录上一次执行时间戳并判断是否超时来决定是否执行。

节流(throttle)是控制高频事件(比如 scroll、resize)执行频率的有效手段,它确保函数在指定时间间隔内最多执行一次,避免因频繁触发导致页面卡顿或重绘压力过大。
节流的核心逻辑:固定间隔只执行一次
与防抖(debounce)不同,节流不等待事件停止,而是“匀速”执行——比如每 100ms 最多调用一次回调。适用于需要持续响应但又不能太密的场景,如滚动时更新吸顶状态、懒加载临界判断等。
- 记录上一次执行的时间戳
- 每次触发时,计算距上次执行是否超过设定延迟
- 满足条件则执行,并更新时间戳;否则跳过
手写一个可靠的 throttle 函数
以下是一个带 leading(首次立即执行)和 trailing(末次补发)选项的通用实现:
function throttle(func, delay, options = {}) {
let lastTime = 0;
const { leading = true, trailing = false } = options;
<p>return function throttled(...args) {
const now = Date.now();
if (!leading && now - lastTime < delay) {
if (trailing && !timeoutId) {
// 延迟补发最后一次(需配合定时器)
let timeoutId;
timeoutId = setTimeout(() => {
func.apply(this, args);
lastTime = Date.now();
timeoutId = null;
}, delay - (now - lastTime));
}
return;
}</p><pre class="brush:php;toolbar:false;">if (now - lastTime >= delay) {
func.apply(this, args);
lastTime = now;
}}; }
更常用且简洁的「仅保证最小间隔」版本(推荐初学者使用):
立即学习“Java免费学习笔记(深入)”;
function throttle(func, delay) {
let lastTime = 0;
return function (...args) {
const now = Date.now();
if (now - lastTime >= delay) {
func.apply(this, args);
lastTime = now;
}
};
}在滚动事件中实际应用
将节流函数包裹处理逻辑后绑定到 scroll,可显著降低 CPU 占用:
const handleScroll = throttle(() => {
const scrollTop = window.pageYOffset;
console.log('当前滚动位置:', scrollTop);
// 例如:判断是否进入某区域、更新导航高亮等
}, 100); // 每 100ms 最多执行一次
<p>window.addEventListener('scroll', handleScroll);注意:
- 不要在每次 scroll 触发时重新创建 throttle 包裹函数(会导致闭包失效、计时重置)
- 若需解绑,请保存 throttled 函数引用:const throttledFn = throttle(...); element.addEventListener('scroll', throttledFn);
现代替代方案:requestIdleCallback + IntersectionObserver
对于非强实时需求(如懒加载图片),优先考虑浏览器原生 API:
-
IntersectionObserver:监听元素是否进入视口,零 JS 计算开销 -
requestIdleCallback:在浏览器空闲时执行低优先级任务,比节流更优雅
节流仍是兼容性好、可控性强的基础方案,适合需要精确时机响应的滚动交互。



















