防抖(Debounce),指在事件被触发后,等待一段时间后再执行回调函数。当在等待的期间内再次触发事件时,就需要重新开始计时。
场景:当搜索框输入时,用户连续输入字符,我们不希望每次输入都发送请求,而是等用户停止输入的一段时间后再发送请求,这样可以减少请求次数,提升性能。
节流(Throttle),指按照固定的时间间隔执行回调函数。不管事件触发有多频繁,都会每隔一段时间执行一次。
场景:滚动事件的处理,如果在滚动过程中不断触发事件,用节流可以确保每隔一定时间处理一次,而不是每次滚动都处理,这样可以避免性能问题。
实际的需求来决定是使用防抖还是节流,比如,窗口调整大小时,假设用户不断调整窗口大小,防抖会在用户停止调整后执行一次,而节流会每隔一段时间执行一次。可能要根据具体需求来选择,如果希望在调整过程中实时反馈,可能用节流更好,否则用防抖。
实现原理
防抖:设置一个定时器,每次事件触发时都清除之前的定时器,重新设置新的定时器。如果在等待时间内没有再次触发事件,定时器到时就执行回调。
节流:
可以通过两种方式实现:时间戳和定时器。
时间戳的方式是在事件触发时比较当前时间与上一次执行的时间差,如果超过设定的间隔,就执行回调。
定时器的方式是在事件触发时设置一个定时器,定时器到时间后执行回调,并清除定时器,这样下次事件触发时再重新设置。
当然可能还需要考虑两者的结合,比如在第一次触发时立即执行,然后在一定时间内不再执行,或者最后一次触发后也要执行一次。比如防抖可能有一个选项,是否立即执行,而节流可能需要确保最后一次触发会被执行。比如,按钮提交的时候,可能希望防抖立即执行一次,然后等待,防止用户多次点击。
在代码实现方面上防抖函数可能需要接受一个函数、等待时间、以及是否立即执行的参数。返回一个被防抖处理的函数。在函数内部,每次调用时清除之前的定时器,然后根据是否立即执行来决定是否立即调用,并设置定时器。而节流的实现可能需要记录上一次执行的时间,或者定时器的状态,来限制执行频率。
总结如下
一、核心概念
防抖(Debounce)
定义:事件触发后,延迟执行回调函数。若在等待期内再次触发事件,则重新计时,直到等待期满后执行。
类比:电梯门关闭逻辑(最后一个人进入后,门才开始关闭)。
适用场景:搜索框输入联想、窗口大小调整结束后的计算、按钮防重复点击。
节流(Throttle)
定义:固定时间间隔内,无论事件触发多频繁,只执行一次回调。
类比:水龙头滴水(无论拧多快,水滴按固定频率落下)。
适用场景:滚动加载更多内容、鼠标移动事件(如拖拽)、高频点击按钮提交。
实现代码
1防抖
通过 setTimeout 控制执行时机,若重复触发则清除旧定时器,创建新定时器。
支持立即执行:首次触发立即执行,后续需等待结束后才能再次触发。
function debounce(func, wait, immediate = false) {
let timeout;
return function (...args) {
const context = this;
const later = () => {
timeout = null;
if (!immediate) func.apply(context, args);
};
const callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setT