JavaScript Memoization 是手动实现的缓存策略,通过 Map 存储参数序列化后的输入输出映射,避免重复计算;但需注意对象/数组键处理、适用场景及性能权衡。

JavaScript Memoization 不是语言内置功能,而是一种手动实现的缓存策略:对相同输入反复调用函数时,跳过重复计算,直接返回之前缓存的结果。
memoize 函数怎么写?
核心逻辑很简单:用一个对象(或 Map)存 input → output 映射。每次调用前先查缓存,命中就返回;没命中就执行原函数、存结果、再返回。
常见错误是把对象或数组当 key 直接用 —— 它们会被转成 "[object Object]",导致所有对象输入都撞同一个缓存项。
- 只对原始类型(
string、number、boolean、symbol)做简单键生成 - 对对象/数组,建议用
JSON.stringify(注意:不能处理函数、undefined、循环引用) - 生产环境推荐用
lodash.memoize或fast-memoize,它们已处理了深比较、this 绑定、maxSize 限制等问题
function memoize(fn) {
const cache = new Map();
return function(...args) {
const key = JSON.stringify(args);
if (cache.has(key)) {
return cache.get(key);
}
const result = fn.apply(this, args);
cache.set(key, result);
return result;
};
}
为什么 useMemo 和 memo 不是 Memoization?
useMemo 和 React.memo 是 React 的优化手段,但和传统 Memoization 有本质区别:
立即学习“Java免费学习笔记(深入)”;
-
useMemo只在依赖数组变化时重新计算,不保证「相同输入必得相同输出」—— 它不校验参数值,只看依赖引用是否变 -
React.memo是对组件的浅层 props 比较,跳过 render,不是函数计算缓存 - 它们都不跨渲染周期保留结果(比如组件卸载后缓存即丢),也不支持自定义键生成逻辑
什么时候用 Memoization 反而更慢?
缓存本身有开销:序列化参数、查表、内存占用。如果函数本身极快(如 a + b),或输入几乎从不重复,加 memoize 就是负优化。
- 适合:高耗时、纯函数、输入重复率高(如递归斐波那契、解析大型 JSON Schema、坐标系转换)
- 不适合:I/O 操作(缓存可能过期)、带副作用的函数、单次调用场景
- 注意副作用泄漏:如果原函数修改了外部变量,缓存后再次调用会跳过该修改,行为不一致
真正难的不是写个 memoize,而是判断哪些函数值得缓存、缓存多久、要不要自动失效——这些得结合业务数据特征来定,没法靠工具自动解决。










