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. 注意事项
- 内存管理:缓存过大可能导致内存问题,需要设置合理的缓存策略
- 参数比较:复杂对象的比较可能需要自定义序列化方法
- 副作用函数:避免对具有副作用的函数使用缓存
这种技术通过牺牲部分内存空间来换取计算性能的提升,在合适的场景下可以显著优化程序性能。