防抖和节流
一、防抖(Debounce)
1.1 什么是防抖?
防抖是一种延迟执行的技术。它的原理是,当事件被触发时,延迟执行事件处理函数,并且在延迟时间内如果事件再次被触发,则重新开始计时。只有当事件在指定的时间内没有再次触发,事件处理函数才会执行。这样可以避免某些高频率的操作被频繁触发,从而提高性能。
也就是你疯狂点我不理你,等你不点了我在处理你最后一次点击
1.2 适用场景
防抖主要适用于那些在用户停止操作后才需要执行的场景,例如:
-
搜索输入框:用户在输入时,连续触发 keyup 事件,只有在输入结束后才发送请求。
-
窗口调整:用户调整浏览器窗口大小时,频繁触发 resize 事件。防抖可以确保调整结束后再执行相应操作。
-
表单验证:用户输入表单数据时,可以用防抖来减少频繁的验证请求。
1.3 实现原理
使用settimeout ,每次点击都清理之前的计时器并创建新的定时器,这样之前的计时器没有执行就被取消了(实现你疯狂点我不理你),留下一个最新的计时器(实现你不点了我处理你最后一次点击)。
所以防抖就是你给朋友安排活,并指定多长时间以后才去干。在他去干之前你给他新的任务的话他当然就不管之前的任务了而开始新任务的计时倒数
/**
* 防抖函数
* @param {Function} func 要防抖的函数
* @param {number} wait 这段时间内再次出发就重新计时
* @returns {Function} 返回防抖后的函数
*/
function Debounce(func, wait) {
let timer = null
//返回防抖后的函数
return function (...agrs) {
//保存当前this指向
const self = this
//清除定时器
timer && clearTimeout(timer)
//设置定时器
timer = setTimeout(() => {
//执行
func.apply(self, agrs)
}, wait)
}
}
二、节流**(Throttle)**
2.1 什么是节流?
节流是一种限制函数执行频率的技术。它的原理是,当事件被频繁触发时,函数会按照一定的时间间隔执行,而不是每次触发事件都执行。换句话说,在一个时间段内,只会执行一次事件处理函数。
也就是你疯狂点吧,反正我就只会按照固定的频率去处理你的请求
2.2 适用场景
节流适用于需要间隔时间执行的场景,例如:
- 页面滚动:用户滚动页面时触发 scroll 事件,使用节流限制处理函数的执行频率。
- 按钮点击:防止用户短时间内多次点击同一个按钮,造成重复提交。
- 游戏动画:限制每秒渲染的帧数,以减少资源消耗。
2.3 实现原理
使用settimeout ,如果存在计时器就不创建新的计时器,当任务执行完毕(或开始)时清空计时器,此时执行的将会是分组中的第一个任务
使用Date.now()获取当前时间,比较距离上一次执行是否已经有设定的时间了,有的话执行并设置新的上一次执行时间,此时执行的将会是分组中的最后一个任务
/**
* 节流函数
* @param {Function} func - 需要节流的函数
* @param {number} wait - 时间间隔(毫秒),表示在这个时间间隔内最多执行一次函数
* @returns {Function} - 返回一个节流后的函数
*/
function Throttle(func, delay) {
let timer = 0
//返回节流后的函数
return function (...args) {
if (!timer) {
timer = setTimeout(() => {
func.apply(this, args)
timer = null
}, delay)
}
}
}
function Throttle(fn, delay) {
let oldTime = Date.now()
//返回节流后的函数
return function (...args) {
let newTime = Date.now()
if (newTime - oldTime >= delay) {
fn.apply(this, args)
oldTime = newTime
}
}
}
三、防抖与节流的区别比较维度
| 比较维度 | 防抖(Debounce) | 节流(Throttle) |
|---|---|---|
| 定义 | 延迟执行,在指定时间内不再触发事件才会执行。 | 限制执行频率,每隔一定时间执行一次。 |
| 触发时机 | 最后一次触发事件后 | 按照固定的时间间隔执行 |
| 适用场景 | 输入框搜索、表单验证、窗口调整 | 页面滚动、按钮点击、游戏动画 |
| 控制频率 | 事件停止后执行一次 | 固定时间间隔内执行一次 |
| 实现原理 | 重新计时,如果时间内再次触发事件则清除计时器 | 记录上次执行时间,或设置定时器 |