js防抖和节流实现
防抖(Debounce)的实现
防抖的核心思想是在事件被触发后,延迟执行回调函数。如果在延迟时间内再次触发事件,则重新计时。适用于输入框搜索、窗口大小调整等场景。
function debounce(func, delay) {
let timer = null;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => {
func.apply(this, args);
}, delay);
};
}
使用示例:
const handleInput = debounce(function(e) {
console.log('Input value:', e.target.value);
}, 500);
document.querySelector('input').addEventListener('input', handleInput);
节流(Throttle)的实现
节流的核心思想是在固定时间间隔内只执行一次回调函数。适用于滚动事件、鼠标移动等高频触发场景。

时间戳版本:
function throttle(func, delay) {
let lastTime = 0;
return function(...args) {
const now = Date.now();
if (now - lastTime >= delay) {
func.apply(this, args);
lastTime = now;
}
};
}
定时器版本:

function throttle(func, delay) {
let timer = null;
return function(...args) {
if (!timer) {
timer = setTimeout(() => {
func.apply(this, args);
timer = null;
}, delay);
}
};
}
使用示例:
const handleScroll = throttle(function() {
console.log('Window scrolled');
}, 200);
window.addEventListener('scroll', handleScroll);
结合版本(leading + trailing)
某些场景需要同时保证首次触发立即执行(leading)和最后一次触发也被执行(trailing):
function throttle(func, delay, options = {}) {
let timer = null;
let lastTime = 0;
const { leading = true, trailing = true } = options;
return function(...args) {
const now = Date.now();
if (!lastTime && !leading) lastTime = now;
const remaining = delay - (now - lastTime);
if (remaining <= 0 || remaining > delay) {
if (timer) {
clearTimeout(timer);
timer = null;
}
func.apply(this, args);
lastTime = now;
} else if (!timer && trailing) {
timer = setTimeout(() => {
func.apply(this, args);
lastTime = leading ? Date.now() : 0;
timer = null;
}, remaining);
}
};
}
注意事项
- 防抖适合处理连续触发但只需要最后一次结果的场景
- 节流适合处理需要均匀间隔执行的场景
- 使用箭头函数时需注意this绑定问题
- 在React等框架中使用时,注意在组件卸载时清除定时器






