原型缓存通过在原型上挂载共享map实现多实例共用缓存,节省内存、提升命中率,适用于纯计算方法;需注意参数序列化、生命周期管理及动态状态依赖等限制。

原型对象本身不直接用于缓存计算结果,但你可以把缓存逻辑“挂载”到原型上,让实例共享同一份缓存空间——这在高频调用、参数稳定、纯计算类方法中很实用。
为什么用原型做缓存比每个实例自己缓存更合适
多个实例反复调用同一个方法(比如 calculateHash() 或 formatDate()),如果每个实例都维护独立缓存,会浪费内存、重复存相同结果。而把缓存放在原型上,所有实例共用一个缓存对象,空间利用率高,命中率也更高。
- 缓存对象只需一份,不随实例数量增长而膨胀
- 适合无副作用、输入输出确定的纯函数式方法
- 避免构造函数里初始化缓存,减少实例创建开销
基础实现:在原型上挂载 Map 缓存
用 Map 存储参数组合 → 结果映射,比普通对象更安全(支持任意类型 key,无原型污染风险):
function Calculator() {}
Calculator.prototype.sum = function(a, b) {
// 缓存挂在原型上,所有实例共享
if (!Calculator.prototype._sumCache) {
Calculator.prototype._sumCache = new Map();
}
const cache = Calculator.prototype._sumCache;
const key = `${a}|${b}`; // 简单参数可用字符串键
if (cache.has(key)) {
return cache.get(key);
}
const result = a + b; // 实际昂贵计算
cache.set(key, result);
return result;
};
注意:这里用字符串拼接作 key,仅适用于原始类型参数;若含对象或数组,需改用 JSON.stringify 或自定义 key 生成逻辑。
进阶要点:控制缓存生命周期和大小
原型缓存一旦创建就长期存在,容易积累无效数据。建议加简单清理机制:
- 手动清空:
Calculator.prototype._sumCache.clear() - 带 TTL 的缓存:存储时记时间戳,读取前校验是否过期
- LRU 限制条目数:用 Map 的插入顺序特性 + 封装 set 方法自动淘汰最久未用项
例如限制最多存 100 条:
function lruSet(map, key, value, max = 100) {
if (map.has(key)) map.delete(key);
map.set(key, value);
if (map.size > max) map.delete(map.keys().next().value);
}
不推荐的场景和注意事项
原型缓存不是万能的,以下情况要谨慎或换方案:
- 方法依赖
this的动态状态(如this.config可变)→ 缓存结果可能失效 - 参数含函数、Symbol、undefined、日期对象等 →
JSON.stringify会丢失信息,需定制 key 生成器 - 多线程/Worker 环境下共享原型缓存不安全 → 改用模块级闭包缓存更稳妥
- 服务端渲染(SSR)中,原型缓存会在请求间泄漏 → 必须按请求隔离
本质上,这是用原型当“轻量单例容器”,核心仍是 memoization 思想,只是作用域从函数闭包移到了原型链上。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











