1. 防抖(来源:彻底搞懂防抖的实现原理(this,闭包等细节)前言 在前端开发中,我们经常需要处理一些高频触发的事件,如窗口的scrol - 掘金 (juejin.cn),作者:反应热 的个人主页 - 文章 - 掘金 (juejin.cn))
debounce 函数(简易版)
javascript
function debounce(fn, delay = 1000) {
let timer = null;
return function(...args) {
const _this = this;
clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(_this, args);
}, delay);
};
}
debounce 函数(健全版)
完整的防抖函数实现
javascript
function debounce(fn, delay = 1000, immediate = false) {
let timer = null;
let lastCallTime = 0;
const later = function(context, args) {
lastCallTime = Date.now();
timer = setTimeout(() => {
timer = null;
if (!immediate) {
fn.apply(context, args);
}
}, delay);
};
return function(...args) {
const context = this;
const now = Date.now();
if (immediate && !timer && (now - lastCallTime >= delay)) {
fn.apply(context, args);
lastCallTime = now;
} else {
clearTimeout(timer);
later(context, args);
}
};
}
// 示例用法
function handleScroll(e) {
console.log('Scroll event:', e);
}
const debouncedHandleScroll = debounce(handleScroll, 300, true);
window.addEventListener('scroll', debouncedHandleScroll);
// 取消防抖函数
function cancelDebounce() {
clearTimeout(timer);
timer = null;
}
// 清除相关资源
window.removeEventListener('scroll', debouncedHandleScroll);
cancelDebounce();
解释
-
参数说明:
fn: 要防抖的函数。delay: 延迟时间,默认为 1000 毫秒。immediate: 是否立即执行,默认为false。
-
内部变量:
timer: 用于存储setTimeout的返回值。lastCallTime: 记录最后一次调用的时间。
-
内部函数
later:- 用于在延迟时间后执行函数。
- 更新
lastCallTime并清除timer。
-
返回的防抖函数:
- 在每次调用时检查
immediate和lastCallTime。 - 如果
immediate为true且没有timer,则立即执行函数。 - 否则,清除现有的
timer并重新设置later。
- 在每次调用时检查
示例用法
假设有一个函数 handleScroll,我们希望在用户停止滚动后 300 毫秒再执行该函数,并且首次调用时立即执行:
javascript
function handleScroll(e) {
console.log('Scroll event:', e);
}
const debouncedHandleScroll = debounce(handleScroll, 300, true);
window.addEventListener('scroll', debouncedHandleScroll);
// 取消防抖函数
function cancelDebounce() {
clearTimeout(timer);
timer = null;
}
// 清除相关资源
window.removeEventListener('scroll', debouncedHandleScroll);
cancelDebounce();
测试
你可以通过以下测试来验证 debounce 函数的效果:
javascript
// 测试函数
function testFunction(e) {
console.log('Called with:', e);
}
// 创建防抖函数
const debouncedTestFunction = debounce(testFunction, 500, true);
// 模拟连续调用
for (let i = 0; i < 10; i++) {
debouncedTestFunction({ detail: i });
setTimeout(() => {}, 100); // 模拟事件循环中的其他操作
}
// 等待一段时间,观察输出
setTimeout(() => {
console.log('After 1 second');
}, 1000);
这个测试会模拟连续调用 testFunction,并在 1 秒后输出一条消息,验证 debounce 函数的效果。
总结
这个防抖函数实现了以下功能:
- 延迟执行:可以在指定的延迟时间后执行函数。
- 立即执行:可以配置是否在第一次调用时立即执行函数。
- 取消:可以在任何时候取消防抖函数。
- 清除:在函数不再需要时可以清除相关资源。
通过这些特性,这个防抖函数更加健壮和灵活,适用于多种场景。