关于 WeakMap 有很多资料,可以参考:
本文主要记录下怎么理解“弱引用”这个概念
弱引用 vs 强引用
我们通过对比 WeakMap 和 Map 来理解弱引用和强引用的区别:
1 | var m = new Map() |
1 | var wm = new WeakMap() |
上面两块代码的内存模型可以大致这么表示:


图一 Foo 对象由于同时被 f 和 Map 对象所引用,其引用计数为 2,而图二中因为是被 WeakMap 对象引用,是弱引用,不计入引用计数,所以值为 1。
弱引用与垃圾回收
如果我们断开 f 对 Foo 对象的引用,则 Foo 对象由于引用计数为 0,会被垃圾回收器回收掉。
1 | var wm = new WeakMap() |

为了验证 WeakMap 起作用了,我们一般会尝试去打印 wm.get(f),结果是 undefined:
1 | var wm = new WeakMap() |
结果满足预期,非常不错!
如果就这样结束了的话,那就太天真了。还是上面的代码,我们把 WeakMap 改成 Map,发现结果也是 undefined。
为什么呢?因为 wm.get(f) 执行的时候,其实执行的是 wm.get(null) ,这个不管是 WeakMap 还是 Map,始终都是 undefined。事实上,当 f 断开了与 Foo 对象的引用后,通往 Foo 对象的唯一通道也被切断了。这样就形成了一个互相矛盾的局面:要让对象可回收,就必须断掉所有的引用;而 WeakMap 需要对象的引用才能执行 get。
那怎么验证 WeakMap 起作用了呢?
如何验证 WeakMap 起作用了
nodejs 中如何验证,这篇文章已经写过了,这里补充一条浏览器中的验证方法:
在 Chrome 浏览器中,我们可以通过开发者工具中的 memory 面板来调试,我们先来调试下 Map:
- 在控制台执行下面代码
1 | var m = new Map() |
- 点击
memory面板中的小圆点,记录当前内存快照,搜索Foo,发现存在一个,可见Foo对象没有被回收。
然后再来试一下 WeakMap:
- 在控制台执行下面代码
1 | var wm = new WeakMap() |
- 点击
memory面板中的小圆点,记录当前内存快照,搜索Foo,发现不存在,可见其已被回收。
总结
一直觉得 WeakMap 应该是个很简单的东西,但是稍微深入下还是挖掘出来不少知识点,以后真不敢“轻视”任何知识了。