一、防抖:
(1) 原理:当一个事件被频繁触发时,防抖技术会推迟函数的执行直到最后一次触发后的一段时间内不再触发。如果在这段延迟时间内又有新的触发,则会重新计时,最后只执行一次实际操作。
例如,在输入框搜索场景中,每次用户键入字符都会触发input事件,但使用防抖处理后,只有当用户停止输入一段时间(如300毫秒)后,才会发送搜索请求。
(2)应用场景:滚动事件实时加载更多内容、窗口大小变化时的布局调整、连续输入时的搜索建议等。
(3)简单示例:
方法一:使用setTimeout清除定时器并重新设置新的定时器
function debounce(func, wait) {
let timeout;
return function(...args) {
if (timeout) clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), wait);
};
}
// 示例使用:
const myFunction = debounce(function(value) {
console.log('The value is:', value);
}, 300);
window.addEventListener('resize', () => {
myFunction(window.innerWidth);
});
方法二:使用闭包存储当前需要执行的函数引用以及定时器标识
function debounce(func, wait) {
let timer;
return function(...args) {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
func.apply(this, args);
timer = null;
}, wait);
};
}
二、节流:
(1)原理:节流是确保在一定时间间隔内,无论事件如何频繁触发,函数至多只执行一次。即从第一次触发开始计算时间间隔,在该间隔期间内,即使多次触发也不会再次执行,直到间隔时间结束才允许下一次执行。
例如,在页面滚动过程中,我们希望每滚动一段距离就更新一次视图,但如果滚动非常快速,我们不希望过于频繁地执行更新逻辑。通过节流处理,可以保证每100毫秒执行一次更新操作,而不是每一次微小的滚动都执行。
(2)应用场景:滚动事件触发的复杂计算、鼠标移动事件的性能优化、频繁调用API导致的网络请求过多问题等。
(3)简单示例:
方法一:基于时间戳的节流函数
function throttle(func, wait) {
let previous = 0; // 上次执行的时间戳
return function(...args) {
const now = Date.now();
// 判断是否达到等待间隔
if (now - previous > wait) {
func.apply(this, args);
previous = now;
}
};
}
// 示例使用:
let throttledFunction = throttle(function(scrollTop) {
console.log('Updating view at scrollTop:', scrollTop);
}, 200);
window.addEventListener('scroll', () => {
throttledFunction(window.pageYOffset);
});
方法二:基于定时器的节流实现:
function throttle(func, wait) {
let timeoutId;
return function(...args) {
if (!timeoutId) { // 只有当没有定时器在运行时才设置新的定时器
timeoutId = setTimeout(() => {
func.apply(this, args);
timeoutId = null; // 定时器执行完毕后清空
}, wait);
}
};
}
三、总结
防抖关注的是“连续动作结束后的那次操作”,适用于短时间内可能有多次操作,但只需执行最后一次的情况。
节流关注的是“固定时间段内的首次操作”,适合于需要周期性执行且不允许太过频繁的情况