WeakMap和Map的区别
- Map的键值可以是原始数据类型和引用类型,WeakMap的键值只能是引用类型
- Map可以迭代遍历键,WeakMap不可迭代遍历键–因为WeakMap的值任何时候都可能被摧毁(第三点垃圾回收),没必要提供迭代其值的能力
- Map所构建的实例是需要手动清理,才能被垃圾回收清除,而WeakMap只要外部的引用消失,所对应的键值对就会自动被垃圾回收清除
很多博客写着WeakMap的键名所指向的对象,不计入垃圾回收机制,一直不理解这个不计入垃圾回收机制的意思,总以为是不能被回收,给想反了,其实是说保存的对象不会增加引用计数器,如果一个对象不被引用了会自动删除
WeakMap限制只能用对象作为键的原因
《JavaScript高级程序设计第四版》说的:是为了保证只有通过键对象的引用才能取得值,如果允许原始值,那就没办法区分初始化时使用的字符串字面量和初始化之后使用的一个相等的字符串。书上P170
理解不来
下面是其他人的理解
因为基础类型是按值传递的。给一个 Map 实例设置一个基础类型的变量为键,就意味着是把这个变量的值复制了一份给 Map 实例,实例中的键与原来的这个变量就失去联系了,即便原来的这个变量的内存被回收了,实例中的键也还存在,重新创建一个同值的变量就可以获得键值对的信息。
而引用类型是按引用传递的。实例中的键其实是对变量内存地址的弱引用(此“弱引用”不影响内存回收,与通常意义上的引用不同),变量一旦被回收,WeakMap 中的“引用”也就被销毁了,大致是这个意思。
对于 Map 而言,内存回收的问题需要开发者自己解决,所以用基础类型没有问题,而开发使用 WeakMap 的动机之一,就是键名失去引用之后能自动回收内存(比如可以用来保存DOM节点,不容易造成内存泄漏,书上P172)