闭包在 memoize 中的核心作用是让缓存对象在函数调用后仍保留在内存中供复用:它通过外层函数创建 cache 并返回能访问该 cache 的内部函数,实现跨调用共享、键生成隔离与生命周期绑定。

闭包在 memoize 中的核心作用是:**让缓存对象(如 Map 或普通对象)在函数调用后依然保留在内存中,供后续调用复用**。它通过将缓存变量定义在外部函数作用域,返回的内部函数“记住”这个变量,从而实现结果持久化。
缓存容器必须被闭包捕获
如果缓存对象(比如 cache = new Map())直接写在全局或每次调用都新建,就无法跨调用共享数据。正确做法是把它放在外层函数里,返回的函数通过作用域链访问它:
- 外层函数(如
memoize(fn))创建并持有cache - 返回的包装函数(
function(...args) { ... })能读写该cache,即使外层函数已执行完毕 - 每次对同一
fn调用memoize,都会生成独立的闭包和独立缓存
键的生成影响缓存命中率
闭包本身不决定怎么存,但为安全构造缓存键提供了环境。常见做法是把参数序列化成唯一字符串作为 key:
- 简单场景可用
JSON.stringify(args)(注意:函数、undefined、Symbol、循环引用会出错) - 更健壮的做法是在闭包内预定义键生成逻辑,比如只取前两个参数、或用自定义哈希函数
- 示例:
const key = args.map(a => typeof a === 'object' ? JSON.stringify(a) : String(a)).join('|')
缓存生命周期由闭包绑定
只要还有对 memoized 函数的引用,闭包里的 cache 就不会被垃圾回收。这意味着:
- 长期存在的 memoized 函数可能导致内存缓慢增长(尤其缓存大量结果时)
- 可结合弱引用(
WeakMap)或手动清理(如加clear()方法)来控制 - 例如在闭包中暴露一个方法:
memoized.clear = () => cache.clear()
实际简易实现示意
下面是一个带缓存清除能力的 memoize 示例,体现闭包如何承载状态:
function memoize(fn) {
const cache = new Map();
const memoized = 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;
};
memoized.clear = () => cache.clear();
return memoized;
}
这里 cache 和 memoized.clear 共享同一个闭包环境,保证了数据一致性与封装性。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











