理解 JavaScript 中的节流和防抖:实现 `throttle` 和 `debounce` 函数

76 阅读2分钟

在前端开发中,频繁触发的事件(如滚动、窗口调整大小、输入框输入等)可能导致性能问题。为了解决这些问题,我们可以使用节流(throttle)和防抖(debounce)技术。这两种技术可以控制函数的执行频率,从而提高性能。本文将详细介绍如何实现和使用 throttledebounce 函数。

什么是节流(throttle)?

节流是指在一定时间间隔内,确保某个函数不会被执行超过一次。即使在该时间间隔内多次触发函数,也只会执行一次。节流通常用于控制连续的事件触发频率,如滚动事件、窗口调整大小事件等。

实现 throttle 函数

下面是实现 throttle 函数的代码:

function throttle(func, delay) {
  let lastTime = 0;  // 记录上一次执行的时间戳

  return function (...args) {
    const currentTime = new Date().getTime();  // 获取当前时间戳

    if (currentTime - lastTime >= delay) {
      func.apply(this, args);  // 执行原始函数
      lastTime = currentTime;  // 更新上一次执行的时间戳
    }
  };
}

// 示例用法
const throttledFunc = throttle(() => {
  console.log("Throttled function is executed!");
}, 1000);

// 触发频率高,但只在1秒内执行一次
setInterval(throttledFunc, 200);

代码解释

  1. 记录上一次执行时间lastTime 用于记录上一次函数执行的时间戳。
  2. 获取当前时间戳currentTime 获取当前的时间戳。
  3. 比较时间差:如果当前时间与上一次执行时间的差值大于或等于设定的延迟时间 delay,则执行函数 func
  4. 更新上一次执行时间:执行函数后,更新 lastTime

什么是防抖(debounce)?

防抖是指在连续的事件中,如果在指定时间内没有再次触发事件,则执行函数。如果在指定时间内再次触发事件,则重新计时。防抖通常用于控制输入框的输入事件处理等。

实现 debounce 函数

下面是实现 debounce 函数的代码:

function debounce(func, delay) {
  let timeoutId;  // 记录定时器ID

  return function (...args) {
    clearTimeout(timeoutId);  // 清除之前的定时器

    timeoutId = setTimeout(() => {
      func.apply(this, args);  // 执行原始函数
    }, delay);
  };
}

// 示例用法
const debouncedFunc = debounce(() => {
  console.log("Debounced function is executed!");
}, 1000);

// 触发频率高,但只在最后一次触发后的1秒内执行一次
for (let i = 0; i < 5; i++) {
  setTimeout(debouncedFunc, 200 * i);
}

代码解释

  1. 记录定时器IDtimeoutId 用于记录当前的定时器ID。
  2. 清除之前的定时器:每次触发函数时,先清除之前的定时器。
  3. 设置新的定时器:重新设置一个定时器,在指定延迟时间 delay 后执行函数 func