WeakMap 的核心是解耦对象生命周期,仅允许天然有销毁机制的对象作键,值须轻量且不反向引用键,统一模块级实例并配合显式清理。

WeakMap 不是用来“管理大对象”的工具,而是用来避免因强引用导致大对象无法释放的机制。团队规范的核心不是“用 WeakMap 存什么”,而是“哪些场景必须用 WeakMap 来解耦生命周期”。关键在约束引用关系,而非操作数据本身。
只允许用对象作键,且该对象必须是外部可销毁的主体
WeakMap 的键只能是对象,且这个对象得是业务中天然存在生命周期管理的实体,比如 DOM 节点、类实例、Canvas 渲染对象等。不能为了塞进 WeakMap 而临时 new 一个空对象当键。
- ✅ 推荐:为每个图表实例附加渲染状态
metadata.set(chartInstance, { isDirty: true }) - ❌ 禁止:
const key = {}; metadata.set(key, data)—— key 没有业务意义,也无法被外部释放 - ⚠️ 注意:Symbol 不能作 WeakMap 键,字符串、数字、null、undefined 均不合法
值必须轻量,禁止反向持有键或形成新强引用链
WeakMap 对键是弱引用,但对值仍是强引用。如果值里又存了键本身(如 { owner: node }),等于变相延长了键的生命周期,泄漏照旧发生。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- ✅ 推荐:值用 plain object、布尔、数字、小数组;例如
{ pending: false, lastUpdate: 1726429500 } - ❌ 禁止:值里存 React 组件实例、大型 ArrayBuffer、整个 Vue 实例、或任何可能引用回键对象的结构
- ⚠️ 特别注意:不要把
get()返回的对象传给setInterval、全局缓存、事件监听器或 Promise 回调 —— 这些都会创建新强引用
统一模块级 WeakMap 实例,禁止随意新建
每个逻辑域(如“图表渲染”、“表单校验”、“拖拽状态”)应有且仅有一个 WeakMap 实例,封装在模块顶层或 class 静态属性中。避免多个 WeakMap 同时跟踪同一类对象,增加排查成本。
立即学习“Java免费学习笔记(深入)”;
- ✅ 推荐:
export const chartState = new WeakMap();放在chart-manager.js顶部 - ❌ 禁止:每个函数内部
new WeakMap(),或组件每次渲染都新建一个 - ? 提示:可用私有字段语法辅助封装,如
#state = new WeakMap(),配合 getter/setter 控制访问
配套清理逻辑必须绑定到明确的销毁钩子
WeakMap 自动清理依赖“键对象失去所有强引用”。但前端对象(如组件、节点)常通过框架或手动方式销毁,需主动触发清理信号,不能只靠 GC 等待。
- ✅ 推荐:在组件
unmounted、disconnectedCallback、或destroy()方法中显式调用weakMap.delete(instance) - ⚠️ 注意:delete 是防御性操作,不影响 GC,但能提前释放值占用的内存,也便于调试追踪
- ? 补充:对无标准销毁钩子的对象(如自由创建的 canvas context),应建立注册-注销机制,由使用者负责调用 unregister

















