[JavaScript] 防抖函数和节流函数
前言
防抖函数和节流函数的区别,可以查看这篇文章,写得比较好:面试官:什么是防抖和节流?有什么区别?如何实现?
防抖(debounce)
防抖函数:主要目的是在一定时间内,如果函数多次被调用,只执行最后一次调用的函数。
执行最后一次是什么意思?如果我频繁点击10次,也就是前面9次都不会执行,只执行最后一次对吗?
假设设置了 delay 为 500ms,并且在短时间内连续点击了10次。
当第一次点击时,防抖函数会设置一个计时器,计划在 500ms 后执行对应的 func。但如果在 500ms 内再次点击,防抖函数会清除上次的计时器,并重新设置一个新的 500ms 计时器。这意味着上次的 func 调用会被取消,不会执行。这个过程会不断重复,每次新的点击都会清除之前的计时器,并重新开始 500ms 的倒计时。
只有当停止点击且最后一次点击后的500ms内不再有新的点击时,防抖函数才会执行这最后一次点击对应的 func。所以,前9次点击都不会触发 func 的执行,只有在点击停止后的 500ms,才会执行最后一次点击的操作。
file:[debounce.ts]
function debounce(func, delay) {
let timer;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => {
func.apply(this, args);
}, delay);
};
}
节流(throttle)
节流函数:节流函数确保在一段时间内,即使触发事件多次,该函数也只会执行一次。
时间戳实现版本:当前时间戳减去上一次点击执行记录的时间戳,如果大于等于定义的 delay 毫秒数就允许执行操作。
file:[throttle.ts]
function throttle(func, delay) {
let lastExecTime = 0;
return function (...args) {
const now = Date.now();
if (now - lastExecTime >= delay) {
func.apply(this, args);
lastExecTime = now;
}
};
}
定时器实现版本:timeoutId 为 null 说明上一个定时器还在,忽略本次操作不执行。当到达了 wait 毫秒数之后执行回调函数,执行完成清除定时器,允许下一次执行。
function throttle(func, wait) {
let timer = null;
return function (...args) {
if (timeoutId) return;
timer = setTimeout(() => {
func.apply(this, args);
timer = null;
}, wait);
};
}