用闭包实现缓存器的核心是将计算结果存储在函数内部,下次相同输入直接返回;需用map作缓存容器以支持任意参数类型,避免序列化陷阱,仅缓存纯函数,并设置容量限制防内存爆炸。

用闭包实现缓存器,核心是把计算结果“记在函数内部”,下次相同输入直接返回,跳过重复运算。关键不在“闭包”本身,而在如何设计缓存结构、判断输入一致性、控制内存增长。
用 Map 做缓存容器,支持任意参数类型
普通对象作缓存时,对象或数组当参数会转成 [object Object] 或 ,,,导致键冲突或全部命中失败。Map 没这个问题,能直接用数组、对象、NaN 甚至函数当 key。
简单示例:
function memoize(fn) {const cache = new Map();
return function(...args) {
// 多参数直接用 args 数组作 key(Map 支持)
if (cache.has(args)) return cache.get(args);
const result = fn(...args);
cache.set(args, result);
return result;
};
}
参数序列化要谨慎:纯字符串/数字优先拼接,复杂对象用稳定哈希
JSON.stringify 看似方便,但遇到 Date、RegExp、undefined、循环引用会出错或生成不一致的 key。不是所有场景都适合它。
- 若参数全是字符串、数字、布尔值,可用
args.join('_')—— 更快、更可控、无副作用 - 含对象或嵌套结构时,引入
fast-deep-equal库比对参数是否相等;或自己写哈希函数(如基于字段名+JSON.stringify(排序后字段值)) - 避免对 DOM 元素、事件对象、函数做缓存 —— 它们每次都是新引用,缓存基本无效
只缓存纯函数,否则结果会“假”
缓存生效的前提是:相同输入,输出恒定。一旦函数里有这些行为,缓存就危险:
- 调用
Date.now()、Math.random()、performance.now() - 发起网络请求(fetch/AJAX)、读取 localStorage
- 修改外部变量、push 到全局数组、触发 DOM 变更
这类函数加缓存后,表面变快了,实则掩盖逻辑错误 —— 比如用户点了两次按钮,第二次没发请求,界面却没更新。
高频场景必须加容量限制,防内存爆炸
Canvas 渲染、滚动监听、鼠标移动等每秒可能调用几十上百次。无节制缓存会让 Map 越来越大,最终拖慢 GC、引发卡顿。
- 手动实现 LRU:缓存设上限(如 100 条),每次 set 前检查 size,超限就删掉最早 entry
- 直接用
lru-cache库,它已内置 max、ttl、dispose 回调等能力 - 对固定组合参数(如 canvas.width + scale),可设计“条件刷新”逻辑:参数变化时主动清空整个缓存
不复杂但容易忽略。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











