记忆化函数通过将函数的输入参数和对应的计算结果进行缓存,当再次传入相同参数时直接返回缓存结果,避免重复执行复杂计算。但在缓存数据过期、内存不足或者需要重新获取最新数据的场景下,就需要清除已有的缓存内容。以下是几种常用的清除JavaScript记忆化函数缓存的实现方式。

直接暴露缓存对象引用
实现记忆化函数时,将缓存对象作为返回函数的一个属性暴露出来,外部可以直接操作这个属性来清除缓存。这种方式实现简单,适合简单的使用场景。
// 实现记忆化函数
function memoize(fn) {
const cache = new Map();
// 返回的记忆化函数
const memoizedFn = 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;
};
// 将缓存对象挂载到函数上
memoizedFn.cache = cache;
return memoizedFn;
}
// 示例函数:计算两数之和
function add(a, b) {
console.log('执行计算');
return a + b;
}
const memoizedAdd = memoize(add);
console.log(memoizedAdd(1, 2)); // 输出 执行计算 3
console.log(memoizedAdd(1, 2)); // 输出 3,使用缓存
// 清除缓存
memoizedAdd.cache.clear();
console.log(memoizedAdd(1, 2)); // 输出 执行计算 3,重新计算
提供专用的清除缓存方法
如果不想直接暴露整个缓存对象,避免外部误操作修改缓存结构,可以在返回的记忆化函数上添加一个专门的清除缓存方法,封装清除逻辑。
function memoizeWithClear(fn) {
const cache = new Map();
const memoizedFn = 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;
};
// 添加清除缓存的方法
memoizedFn.clearCache = function() {
cache.clear();
};
// 可选:添加获取缓存大小的方法
memoizedFn.getCacheSize = function() {
return cache.size;
};
return memoizedFn;
}
function multiply(a, b) {
console.log('执行乘法计算');
return a * b;
}
const memoizedMultiply = memoizeWithClear(multiply);
console.log(memoizedMultiply(2, 3)); // 输出 执行乘法计算 6
console.log(memoizedMultiply(2, 3)); // 输出 6
console.log(memoizedMultiply.getCacheSize()); // 输出 1
// 调用清除方法
memoizedMultiply.clearCache();
console.log(memoizedMultiply.getCacheSize()); // 输出 0
console.log(memoizedMultiply(2, 3)); // 输出 执行乘法计算 6
使用WeakMap实现自动缓存清除
如果记忆化函数的参数是对象类型,可以使用WeakMap存储缓存,WeakMap的键是弱引用,当对象没有其他引用时会被自动垃圾回收,无需手动清除缓存,适合参数为对象的场景。
function memoizeWithWeakMap(fn) {
const cache = new WeakMap();
return function(arg) {
// 仅支持单个对象参数,如需多参数可调整key生成逻辑
if (cache.has(arg)) {
return cache.get(arg);
}
const result = fn.call(this, arg);
cache.set(arg, result);
return result;
};
}
// 示例函数:获取对象的属性数量
function getObjPropCount(obj) {
console.log('计算对象属性数量');
return Object.keys(obj).length;
}
const memoizedGetPropCount = memoizeWithWeakMap(getObjPropCount);
const testObj = { a: 1, b: 2 };
console.log(memoizedGetPropCount(testObj)); // 输出 计算对象属性数量 2
console.log(memoizedGetPropCount(testObj)); // 输出 2,使用缓存
// 移除testObj的引用后,WeakMap中的缓存会被自动回收
// 实际应用中无需手动清除,依赖垃圾回收机制即可
不同清除方式的适用场景
可以根据实际开发需求选择合适的缓存清除方式,以下是不同方式的特点对比:
| 清除方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 暴露缓存引用 | 实现简单,可直接操作缓存 | 缓存结构完全暴露,易被误操作 | 简单工具函数,内部使用场景 |
| 提供专用清除方法 | 封装清除逻辑,安全性更高 | 需要额外定义方法 | 对外提供的公共记忆化函数 |
| WeakMap自动清除 | 无需手动清除,内存友好 | 仅支持对象作为键,兼容性稍弱 | 参数为对象的记忆化场景 |
注意事项
- 生成缓存键时如果使用
JSON.stringify,要注意参数中包含函数、循环引用等无法序列化的情况,需要自定义键生成逻辑。 - 手动清除缓存后,如果后续还需要使用记忆化功能,函数会重新计算并缓存新结果,不会影响后续使用。
- 如果记忆化函数需要支持多上下文调用,缓存时要注意
this的指向问题,必要时将上下文也作为缓存键的一部分。
memoizationclosure缓存清除JavaScript修改时间:2026-07-01 14:30:17