缓存函数利用闭包保存输入→输出映射以避免重复计算;外层函数创建缓存对象,返回的内层函数共享该缓存且阻止其被垃圾回收;基础版支持单参数,进阶版需序列化多参数或复杂类型为唯一键;仅适用于纯函数,需注意内存泄漏、this绑定及异步处理。

缓存函数(也叫记忆化函数,memoization)利用闭包保存已计算的结果,避免重复执行相同输入的耗时操作。核心在于:用一个对象(或 Map)在闭包中记住 输入 → 输出 的映射,后续相同输入直接返回缓存值。
闭包如何保存缓存数据
闭包让内部函数能持续访问外层函数作用域中的变量。缓存函数把缓存容器(比如 cache = {})定义在外层,返回的内层函数每次调用都可读写它,而这个变量不会被垃圾回收——因为它被返回的函数“捕获”了。
- 外层函数只执行一次,生成专属缓存空间
- 返回的函数每次调用都共享同一份缓存
- 缓存生命周期与返回函数的生命周期一致
基础实现:支持单参数的缓存函数
适用于参数是字符串、数字等可安全作为对象键的场景:
function memoize(fn) {
const cache = {};
return function(arg) {
if (arg in cache) {
return cache[arg];
}
const result = fn(arg);
cache[arg] = result;
return result;
};
}
// 使用示例
const expensiveAdd = memoize(x => {
console.log('计算中...');
return x + x;
});
expensiveAdd(5); // 打印"计算中...",返回10
expensiveAdd(5); // 不打印,直接返回10
进阶:支持多参数和复杂类型键
当函数有多个参数,或参数含对象、数组等引用类型时,不能直接用 args in cache。需将参数序列化为唯一字符串键(注意:JSON.stringify 有局限,如忽略函数、undefined、Symbol,且对象属性顺序敏感):
立即学习“Java免费学习笔记(深入)”;
- 用
JSON.stringify(args)作简易键(适合纯 JSON 数据) - 更健壮可用
Map+ 自定义 key 生成逻辑(如用逗号拼接基本类型,或用 WeakMap 存对象引用) - 生产环境推荐使用
lodash.memoize或自定义哈希函数处理边界情况
注意事项和常见坑
缓存不是万能的,用错反而影响性能或逻辑:
- 纯函数才适合缓存——输出只依赖输入,无副作用
- 缓存不清理会持续占用内存,必要时加最大容量限制或 LRU 策略
- 慎用于 this 绑定或依赖外部状态的函数(闭包捕获的是定义时的 this,不是调用时的)
- 异步函数需单独处理(如缓存 Promise 实例,避免多次触发请求)


















