JavaScript中的函数缓存(Memoization)
字数 550 2025-11-13 13:02:59

JavaScript中的函数缓存(Memoization)

函数缓存是一种优化技术,通过存储函数调用的结果,当后续使用相同参数调用时直接返回缓存结果,避免重复计算。这在计算密集型或递归函数中特别有用。

1. 基本概念

  • 核心思想:用空间换时间,将输入参数作为键,计算结果作为值存储在缓存对象中
  • 适用场景:纯函数(同样输入必然得到同样输出)、计算成本高的函数
  • 不适用场景:非纯函数、参数数量不固定、参数包含复杂对象的情况

2. 基础实现步骤

function memoize(func) {
  const cache = {}; // 创建缓存对象
  
  return function(...args) {
    const key = JSON.stringify(args); // 将参数序列化为缓存键
    
    if (cache[key] !== undefined) {
      console.log('从缓存中获取结果');
      return cache[key];
    }
    
    console.log('计算新结果');
    const result = func.apply(this, args);
    cache[key] = result;
    return result;
  };
}

3. 具体使用示例

// 原始计算函数
function expensiveCalculation(n) {
  console.log(`计算 ${n} 的阶乘`);
  let result = 1;
  for (let i = 1; i <= n; i++) {
    result *= i;
  }
  return result;
}

// 应用缓存
const memoizedCalculation = memoize(expensiveCalculation);

console.log(memoizedCalculation(5)); // 计算新结果,返回120
console.log(memoizedCalculation(5)); // 从缓存中获取结果,返回120
console.log(memoizedCalculation(3)); // 计算新结果,返回6

4. 处理复杂情况

  • this绑定问题:确保函数执行时的正确上下文
  • 对象参数:使用更复杂的序列化方法或Map结构
  • 缓存限制:添加缓存大小限制防止内存泄漏
function advancedMemoize(func, options = {}) {
  const cache = new Map();
  const { maxSize = 100 } = options;
  
  return function(...args) {
    // 创建更可靠的键(处理循环引用等特殊情况)
    const key = args.map(arg => {
      if (typeof arg === 'object' && arg !== null) {
        return JSON.stringify(arg, (key, value) => {
          if (typeof value === 'object' && value !== null) {
            return Object.keys(value).sort().reduce((result, key) => {
              result[key] = value[key];
              return result;
            }, {});
          }
          return value;
        });
      }
      return arg;
    }).join('|');
    
    if (cache.has(key)) {
      return cache.get(key);
    }
    
    // 缓存大小控制
    if (cache.size >= maxSize) {
      const firstKey = cache.keys().next().value;
      cache.delete(firstKey);
    }
    
    const result = func.apply(this, args);
    cache.set(key, result);
    return result;
  };
}

5. 递归函数的缓存优化

// 斐波那契数列的缓存优化
const fibonacci = memoize(function(n) {
  if (n <= 1) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
});

console.log(fibonacci(10)); // 55,大幅减少计算次数

6. 实际应用场景

  • 数学计算:阶乘、斐波那契数列等
  • API响应缓存:相同请求返回缓存结果
  • 组件渲染优化:React useMemo、useCallback的实现原理
  • 图像处理:重复滤镜效果的计算缓存

7. 注意事项

  • 内存管理:缓存过大可能导致内存问题,需要设置合理的缓存策略
  • 参数比较:复杂对象的比较可能需要自定义序列化方法
  • 副作用函数:避免对具有副作用的函数使用缓存

这种技术通过牺牲部分内存空间来换取计算性能的提升,在合适的场景下可以显著优化程序性能。

JavaScript中的函数缓存(Memoization) 函数缓存是一种优化技术,通过存储函数调用的结果,当后续使用相同参数调用时直接返回缓存结果,避免重复计算。这在计算密集型或递归函数中特别有用。 1. 基本概念 核心思想:用空间换时间,将输入参数作为键,计算结果作为值存储在缓存对象中 适用场景:纯函数(同样输入必然得到同样输出)、计算成本高的函数 不适用场景:非纯函数、参数数量不固定、参数包含复杂对象的情况 2. 基础实现步骤 3. 具体使用示例 4. 处理复杂情况 this绑定问题 :确保函数执行时的正确上下文 对象参数 :使用更复杂的序列化方法或Map结构 缓存限制 :添加缓存大小限制防止内存泄漏 5. 递归函数的缓存优化 6. 实际应用场景 数学计算:阶乘、斐波那契数列等 API响应缓存:相同请求返回缓存结果 组件渲染优化:React useMemo、useCallback的实现原理 图像处理:重复滤镜效果的计算缓存 7. 注意事项 内存管理:缓存过大可能导致内存问题,需要设置合理的缓存策略 参数比较:复杂对象的比较可能需要自定义序列化方法 副作用函数:避免对具有副作用的函数使用缓存 这种技术通过牺牲部分内存空间来换取计算性能的提升,在合适的场景下可以显著优化程序性能。