js中防抖和节流实现
防抖(Debounce)
防抖的核心思想是在事件触发后,等待一定时间间隔(如 n 毫秒)再执行回调。如果在这段时间内事件再次被触发,则重新计时。
基础实现:
function debounce(func, delay) {
let timeoutId;
return function(...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
func.apply(this, args);
}, delay);
};
}
应用场景:
- 搜索框输入联想(避免频繁请求)
- 窗口大小调整事件(避免频繁计算布局)
立即执行版本:

function debounceImmediate(func, delay, immediate = true) {
let timeoutId;
return function(...args) {
const context = this;
const callNow = immediate && !timeoutId;
clearTimeout(timeoutId);
timeoutId = setTimeout(() => {
timeoutId = null;
if (!immediate) func.apply(context, args);
}, delay);
if (callNow) func.apply(context, args);
};
}
节流(Throttle)
节流的核心思想是在固定时间间隔(如 n 毫秒)内只执行一次回调,无论事件触发多少次。
时间戳实现:

function throttle(func, limit) {
let lastTime;
return function(...args) {
const now = Date.now();
if (!lastTime || now - lastTime >= limit) {
func.apply(this, args);
lastTime = now;
}
};
}
定时器实现:
function throttle(func, limit) {
let timeoutId;
return function(...args) {
if (!timeoutId) {
timeoutId = setTimeout(() => {
func.apply(this, args);
timeoutId = null;
}, limit);
}
};
}
结合版本(首尾均执行):
function throttle(func, limit) {
let timeoutId, lastTime = 0;
return function(...args) {
const now = Date.now();
const remaining = limit - (now - lastTime);
if (remaining <= 0) {
if (timeoutId) {
clearTimeout(timeoutId);
timeoutId = null;
}
func.apply(this, args);
lastTime = now;
} else if (!timeoutId) {
timeoutId = setTimeout(() => {
func.apply(this, args);
lastTime = Date.now();
timeoutId = null;
}, remaining);
}
};
}
应用场景:
- 滚动事件监听(如无限滚动加载)
- 鼠标移动事件(如拖拽元素)
注意事项
this绑定:使用func.apply(this, args)确保回调函数中的this指向正确。- 参数传递:通过
...args保留事件参数。 - 取消机制:可扩展实现
cancel方法清除定时器。 - 性能考量:高频事件(如
mousemove)建议使用requestAnimationFrame替代setTimeout。






