weakmap适合在状态机中缓存中间结果,关键在于用状态机实例(对象)作key,避免内存泄漏且随实例销毁自动清理;不可用于长期缓存、临时对象作key或需调试监控的场景。

WeakMap 适合在状态机中缓存中间结果,关键在于用状态机实例(对象)作 key,避免内存泄漏,同时保证计算结果随实例生命周期自动清理。
用 WeakMap 缓存状态相关计算结果
状态机通常以对象形式存在(如 class 实例),其内部状态变化频繁,但某些派生值(如格式化后的上下文、校验结果、转换后的配置)计算开销大且依赖当前状态。WeakMap 允许你把这类值绑定到实例本身,而不阻止垃圾回收:
- key 必须是对象(如 this 或 stateRef),不能是字符串或原始值
- 只要状态机实例被销毁,WeakMap 中对应的条目自动消失,无需手动清理
- 无法遍历或清空 WeakMap,天然契合“隐式生命周期绑定”场景
典型缓存模式:按状态快照生成唯一 key
如果状态机支持多个“逻辑状态”(如 'idle' | 'loading' | 'error'),而某些计算只依赖当前状态 + 部分输入,可构造轻量 key 对象作为 WeakMap 的键:
将一个或多个视频上传至YouTube。当用户想“上传到YouTube”“发YouTube”“批量上传”“upload to YouTube”“post videos to YouTube”或发布到YouTube时使用此技能。
// 不直接用字符串,而是用一个仅含状态标识的对象
const cache = new WeakMap();
function getDerivedData(stateMachine) {
const cacheKey = { status: stateMachine.status };
let result = cache.get(stateMachine);
if (!result || result.key !== cacheKey.status) {
result = { key: cacheKey.status, value: expensiveCalc(stateMachine) };
cache.set(stateMachine, result);
}
return result.value;
}
注意:这里仍用 stateMachine 作 WeakMap 的 key,而非 cacheKey —— 因为 cacheKey 是临时对象,无法稳定追踪;真正需要绑定生命周期的是状态机实例本身。
结合私有字段与 WeakMap 实现封装
ES2022+ 支持私有字段,配合 WeakMap 可隐藏缓存细节,避免外部干扰:
- 定义私有缓存容器:
static #cache = new WeakMap(); - 在 getter 或方法中检查并填充:
#cache.has(this) ? #cache.get(this) : this.#computeAndCache() - 确保所有中间结果只通过 this 访问,不暴露缓存结构
什么情况下不该用 WeakMap 缓存?
WeakMap 不适合以下场景:
- 需要长期保留结果(如全局配置预处理),应改用 Map 或普通对象
- key 是临时对象(如每次调用都 new {}),会导致缓存失效且无法回收
- 需调试或监控缓存命中率——WeakMap 无法枚举,建议开发环境用 Map 替代,生产再切回 WeakMap
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










