闭包缓存库通过封装私有Map实现安全数据管理,支持基础CRUD、TTL过期和函数结果记忆化;需注意key序列化可靠性、内存控制及对象引用问题。

用闭包实现一个简单的缓存库,核心是利用闭包捕获并维护一个私有的数据结构(比如对象或 Map),同时暴露有限的、安全的操作接口。这样既能避免全局污染,又能封装内部状态,防止外部直接修改缓存数据。
基础结构:闭包封装缓存存储
闭包让内部变量(如 cache)在函数执行完后仍保留在内存中,且只能通过返回的函数访问:
function createCache() {
const cache = new Map(); // 或用普通对象 {},但 Map 更适合键为对象/函数等场景
<p>return {
get(key) {
return cache.get(key);
},
set(key, value) {
cache.set(key, value);
},
has(key) {
return cache.has(key);
},
delete(key) {
return cache.delete(key);
},
clear() {
cache.clear();
}
};
}</p><p>// 使用
const myCache = createCache();
myCache.set('user:123', { id: 123, name: 'Alice' });
console.log(myCache.get('user:123')); // { id: 123, name: 'Alice' }
支持过期时间(TTL)的增强版
真实缓存常需自动失效。可在 set 时存入时间戳,在 get 时检查是否过期:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
function createTtlCache(ttlMs = 5 * 60 * 1000) { // 默认 5 分钟
const cache = new Map();
<p>return {
get(key) {
const entry = cache.get(key);
if (!entry) return undefined;</p><pre class="brush:php;toolbar:false;"> const now = Date.now();
if (now - entry.timestamp > ttlMs) {
cache.delete(key);
return undefined;
}
return entry.value;
},
set(key, value) {
cache.set(key, {
value,
timestamp: Date.now()
});
},
has(key) {
const entry = cache.get(key);
if (!entry) return false;
return Date.now() - entry.timestamp <= ttlMs;
},
clear() {
cache.clear();
}}; }
带计算逻辑的 memoized 缓存(自动缓存函数结果)
这是闭包缓存最典型的用法之一:把函数调用结果按参数缓存,避免重复计算:
立即学习“Java免费学习笔记(深入)”;
function memoize(fn) {
const cache = new Map();
<p>return function(...args) {
// 将参数转为可序列化的唯一 key(简单起见用 JSON.stringify,注意函数/undefined/循环引用不适用)
const key = JSON.stringify(args);</p><pre class="brush:php;toolbar:false;">if (cache.has(key)) {
return cache.get(key);
}
const result = fn(...args);
cache.set(key, result);
return result;}; }
// 使用 const expensiveAdd = memoize((a, b) => { console.log('计算中...'); return a + b; });
console.log(expensiveAdd(2, 3)); // 计算中... → 5 console.log(expensiveAdd(2, 3)); // 直接返回 5(不打印)
注意事项和实用建议
-
key 的可靠性:用
JSON.stringify生成 key 简单但有局限(如{a:1,b:2}和{b:2,a:1}序列化结果不同)。生产环境建议用更健壮的 key 生成库(如serialize-javascript或自定义标准化逻辑) -
内存管理:长期运行的缓存需考虑大小限制或 LRU 策略。可用
lru-cache库替代手写,或在闭包内加maxSize和淘汰逻辑 - 引用类型注意:如果缓存对象被外部修改,会影响后续读取结果。必要时做浅拷贝或深克隆(但会增加开销)
- 线程安全?:JavaScript 单线程,无需锁机制;但多个闭包实例之间完全隔离,互不影响

















