笔记小计

76 阅读2分钟

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();

解释

  1. 参数说明

    • fn: 要防抖的函数。
    • delay: 延迟时间,默认为 1000 毫秒。
    • immediate: 是否立即执行,默认为 false
  2. 内部变量

    • timer: 用于存储 setTimeout 的返回值。
    • lastCallTime: 记录最后一次调用的时间。
  3. 内部函数 later

    • 用于在延迟时间后执行函数。
    • 更新 lastCallTime 并清除 timer
  4. 返回的防抖函数

    • 在每次调用时检查 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 函数的效果。

总结

这个防抖函数实现了以下功能:

  • 延迟执行:可以在指定的延迟时间后执行函数。
  • 立即执行:可以配置是否在第一次调用时立即执行函数。
  • 取消:可以在任何时候取消防抖函数。
  • 清除:在函数不再需要时可以清除相关资源。

通过这些特性,这个防抖函数更加健壮和灵活,适用于多种场景。