image.png

答案:

1)Set

成员唯一、无序且不重复;
[value, value],键值与键名是一致的(或者说只有键值,没有键名);
可以遍历,方法有:add、delete、has、size、clear。

2)WeakSet

成员都是对象;
成员都是弱引用,可以被垃圾回收机制回收,可以用来保存DOM节点,不容易造成内存泄漏
不能遍历,方法有 add、delete、has。

3)Map

本质上是键值对的集合,类似集合;
可以遍历,方法很多,可以跟各种数据格式转换。

  • size
  • has、get、set、clear
  • [@@iterator]/entries/forEach/keys/set/values

  1. let myMap = new Map([
  2. [1, 'one'],
  3. [2, 'two'],
  4. [3, 'three'],
  5. ])
  6. myMap
  7. [object Map] { ... }
  8. myMap.get(1)
  9. "one"
  10. [...myMap]
  11. [[1, "one"], [2, "two"], [3, "three"]]
  12. myMap.keys()
  13. [object Map Iterator] { ... }

4)WeakMap

只接受对象作为键名(null 除外),不接受其他类型的值作为键名;
键名是弱引用,键值可以是任意的,键名所指向的对象可以被垃圾回收,此时键名是无效的;

  • 没有size
  • get、set、has、delete、没有clear
  • 不能遍历

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/WeakMap

WeakMap 不会阻止垃圾回收机制对对象的回收

map是强引用, weakmap是弱引用

应用: WeakMap缓存计算结果

  1. // cache.js
  2. let cache = new WeakMap();
  3. function process(person) {
  4. if (!cache.has(person)) {
  5. let score = 98; // clac
  6. cache.set(person, score);
  7. }
  8. return cache.gget(person)
  9. }
  10. // index.js
  11. let p1 = {name: 'Jack'}
  12. let s1 = process(p1);
  13. // need remove p1
  14. p1 = null;

[实践] node gc对比map 和 weakmap

  1. // node --expose-gc index.js
  2. global.gc();
  3. console.log(process.memoryUsage().heapTotal.toLocaleString());
  4. // let cache = new WeakMap();
  5. let cache = new Map();
  6. let k1 = new Array(1024 * 1024);
  7. cache.set(k1, null);
  8. global.gc();
  9. console.log(process.memoryUsage().heapTotal.toLocaleString());
  10. k1 = null;
  11. // delete k1;
  12. // console.log(Object.keys(cache)); []
  13. global.gc();
  14. console.log(process.memoryUsage().heapTotal.toLocaleString());
初始内存 新增后的内存 减小key后的内存
map 5,881,856 14,278,656 16,375,808 截屏2022-05-31 上午8.21.36.png
weakmap 5,881,856 14,278,656 7,979,008 截屏2022-05-31 上午8.21.43.png