Memoization 是通过缓存函数结果避免重复计算的优化技术,适用于纯函数;用 Map 缓存、需确保纯性、注意内存清理;示例实现用 JSON.stringify 生成 key。

Memoization 是一种通过缓存函数已计算结果来避免重复执行的优化技术,特别适合纯函数(相同输入总返回相同输出、无副作用)。
核心原理:用空间换时间
函数首次被调用时,把输入参数作为 key,返回值作为 value 存入缓存(通常是 JavaScript 对象或 Map);后续相同输入直接从缓存取值,跳过实际运算。
- 缓存结构推荐用 Map(支持任意类型 key,如对象、函数、Symbol)而非普通对象(只适合字符串/数字 key)
- 必须确保函数是纯的,否则缓存可能返回过期或错误结果
- 注意内存占用——长期运行的程序需考虑缓存清理策略(如 LRU、TTL 或手动清除)
手写一个基础 memoize 工具函数
以下是一个轻量、通用的实现:
function memoize(fn) {
const cache = new Map();
return function(...args) {
const key = JSON.stringify(args); // 简单序列化(仅适用于可 JSON 化参数)
if (cache.has(key)) {
return cache.get(key);
}
const result = fn.apply(this, args);
cache.set(key, result);
return result;
};
}
使用示例:
立即学习“Java免费学习笔记(深入)”;
const fibonacci = memoize(n => n <= 1 ? n : fibonacci(n - 1) + fibonacci(n - 2)); fibonacci(35); // 首次较慢,但后续调用极快
进阶:处理复杂参数与上下文
JSON.stringify 无法正确处理函数、undefined、Date、RegExp、循环引用等。生产环境建议:
- 用 fast-deep-equal 或 lodash.isEqual 实现深度参数比对(配合自定义 key 生成)
- 若函数依赖 this,需在闭包中绑定上下文或使用 fn.call(this, ...args)
- 可扩展支持 options:maxSize(限制缓存条目数)、ttl(过期时间)、cacheKey(自定义 key 生成函数)
何时不该用 memoization?
不是所有函数都适合加 memo:
- 输入组合极少,或几乎不会重复调用(缓存反而增加开销)
- 函数本身极快(如简单加法),缓存查找成本可能高于重新计算
- 参数含不可序列化值且无可靠 key 生成方式
- 函数有副作用(如发请求、修改 DOM),缓存会掩盖行为,破坏预期逻辑











