计算属性缓存本质是用闭包封装私有Map实现“输入→输出”固化映射:每个getter由独立工厂生成,隔离缓存;key需标准化避免引用陷阱;每次调用执行查表-计算-写入闭环;提供clear()显式清理。

直接用 Map 存储计算属性的闭包结果,本质是把“输入 → 输出”映射固化在内存中,再通过闭包封装访问逻辑,让 getter 表面无状态、实际带缓存。关键不在 Map 本身,而在于如何用闭包把 Map 的生命周期、键生成、失效控制全链路收束起来。
闭包初始化私有 Map,隔离缓存作用域
每个计算属性 getter 应由独立工厂函数生成,内部声明一个 Map 实例,并返回仅暴露 get 逻辑的函数:
- Map 声明在闭包顶层,不对外暴露引用,避免误删或污染
- 返回的 getter 函数闭包持有该 Map,保证多次调用共享同一缓存容器
- 不同属性调用各自工厂(如 createComputedGetter(fnA)、createComputedGetter(fnB)),缓存天然隔离,互不影响
构造稳定、可复用的 key,避开引用陷阱
key 决定缓存是否命中。不能直接用参数对象或数组——因为每次新建引用都不同。需按语义标准化:
- 纯基础类型参数(如 string/number/boolean):用 JSON.stringify([a, b, c]) 生成字符串 key,简单有效
- 含对象/函数参数:若只依赖其结构(如配置项),先 structuredClone 后 stringify;若只关心身份(如单个 DOM 元素),改用 WeakMap + 闭包内缓存,但注意 WeakMap 不支持非对象 key
- 避免在 key 构造中捕获外部变量(如组件 props 或 state),否则相同输入因上下文不同产生不同 key,缓存失效
getter 内部完成查表、计算、写入三步闭环
每次调用 getter 时,不假定缓存存在或新鲜,而是主动执行完整流程:
- 根据当前参数生成 key
- 用 map.has(key) 判断是否存在有效结果
- 存在则 map.get(key) 直接返回;不存在则执行原计算函数,map.set(key, result) 后返回
- 不自动清理旧值,但也不允许过期数据滞留——若计算逻辑依赖外部可变状态(如全局配置),需额外设计 forceRefresh 接口或监听变更后 clear()
配套清理机制,防止内存持续增长
高频 getter 若长期运行,缓存可能累积大量冷数据。需主动干预:
- 提供 clear() 方法暴露在 getter 外层对象上,供业务侧在卸载、切换、重置时调用
- 对有明确生命周期的场景(如 React 组件),在 useEffect cleanup 或 componentWillUnmount 中调用 clear()
- 不依赖定时器自动扫描——除非缓存规模极大且访问稀疏;多数前端场景靠显式清理更可控、无副作用

















