WeakMap 能不能用来缓存 DOM 元素的计算结果?

夏侯馨然 阅读 4

我在做一个动态表格,想用 WeakMap 缓存每个单元格的格式化结果,避免重复计算。但发现缓存好像没生效,是不是我用错了?

我试过这样写:

const cache = new WeakMap();

function formatCell(cell) {
  if (cache.has(cell)) {
    return cache.get(cell);
  }
  const result = expensiveFormat(cell.textContent);
  cache.set(cell, result);
  return result;
}

但每次调用 formatCell 都重新计算了,WeakMap 里的值似乎被清掉了。DOM 元素不是还在页面上吗?为啥缓存不住?

我来解答 赞 3 收藏
二维码
手机扫码查看
1 条解答
上官嘉煊
你这代码逻辑本身没毛病,WeakMap 用来缓存 DOM 元素完全可行,DOM 元素确实是对象引用,只要元素还在页面上、没有被 GC 回收,缓存就不会丢。

问题大概率出在作用域上。仔细检查一下你的 cache 变量是不是每次都重新创建了。我见过太多人把 const cache = new WeakMap() 写在函数内部或者某个会重复执行的代码块里,那每次调用肯定都是空的 WeakMap 啊。

正确的写法应该是把 cache 提到外面去:

// cache 必须在函数外部,保持单例
const cache = new WeakMap();

function formatCell(cell) {
if (cache.has(cell)) {
return cache.get(cell);
}
const result = expensiveFormat(cell.textContent);
cache.set(cell, result);
return result;
}


还有个常见坑,如果你的表格是动态渲染的,比如用框架或者 innerHTML 重写了表格内容,那原来的 DOM 元素引用就失效了,WeakMap 里对应的缓存自然也被清理掉。这种情况用 WeakMap 反而是对的,因为它不会造成内存泄漏,只是你需要接受"重新计算一次"这个代价。

WP里面做复杂交互的时候也常遇到这问题,建议你在 cache.set 那行加个 console.log('设置缓存', cell),看看是不是调用次数比你预期的多,这样能快速定位是作用域问题还是 DOM 重建问题。
点赞
2026-03-02 23:30