ES6里的 Set、Map、WeakMap的区别

244 阅读3分钟

ES6里的 Set、Map、WeakMap的区别

Set

类似数组,但成员的值都是唯一的,没有重复的值,本身是一个构造函数,[value,value] 键名与键值一致,可遍历 Set结构的实例属性:

  • Set.prototype.size // 返回Set 实例成员的总数
  • Set.prototype.constructor // 构造函数,默认指向Set 函数

Set实例具有的方法,分为两类

  1. 操作数据
    • add(value) // 添加某个值,返回Set 结构本身
    • delete(value) // 删除某个值,返回Boolean 值
    • has(value) // 判断是否存在某个值, 返回Boolean 值
    • clear() // 清除所有成员,没有返回值
  2. 遍历:
    • keys() // 返回键名的遍历器
    • values() // 返回键值的遍历器
    • entries() // 返回键值对的遍历器
    • forEach() // 使用回调函数遍历每一个成员

使用 Set 可以实现数组去重

    [...new Set(array)]

Map

Map 本质是键值对的集合,key可以是任何数据类型,同Set数据结构,属性和方法也可以按以下进行分类

Set结构的实例属性:

  • Set.prototype.size // 返回Map 结构成员的总数
  • Set.prototype.constructor // 构造函数,默认指向Map 函数

Set实例具有的方法,分为两类

  1. 操作数据
    • set(key,value) // 添加某个key的值为value,返回整个Map 结构本身
    • get(key) // 读取key对应的value, 如果未读取到返回 undefined
    • delete(key) // 删除某个key,返回Boolean 值
    • has(key) // 判断是否存在某个key, 返回Boolean 值
    • clear() // 清除所有成员,没有返回值
  2. 遍历:
    • keys() // 返回键名的遍历器
    • values() // 返回键值的遍历器
    • entries() // 返回所有成员的遍历器
    • forEach() // 使用回调函数遍历每一个成员

WeakMap

类似Map,区别:

- key只接受对象(null 除外);
- key 指向的对象是弱引用,不计入垃圾回收机制 ;
- weakMap 不可遍历,也没有size 属性

只有4个方法可用:

- get(key)
- set(key)
- has(key)
- delete(key)
  1. 新建一个map.js,执行命令: node --expose-gc map.js
function usedSize() {
    const used = process.memoryUsage().heapUsed;
    return Math.round((used / 1024 / 1024) * 100) / 100 + "M";
}

global.gc(); // 0 每次查询内存都先执行gc()再memoryUsage(),是为了确保垃圾回收,保证获取的内存使用状态准确

console.log(usedSize()); // 1 初始状态,执行gc()和memoryUsage()以后,heapUsed 值为 4M

var map = new Map();
var a = new Array(10 * 1024 * 1024);

map.set(a, 1);

global.gc();
console.log(usedSize()); // 2 在 Map 中加入元素a,为一个 10*1024*1024 的数组后,heapUsed为83.88M左右

a = null;
global.gc();

console.log(usedSize()); // 3 将a置为空以后,heapUsed 仍为83.89M左右,说明Map中的那个长度为5*1024*1024的数组依然存在

image.png

**可以看到map中数组a依然存在 **

  1. 新建一个weakMap.js,执行命令: node --expose-gc weakMap.js
// weakmap.js
function usedSize() {
   const used = process.memoryUsage().heapUsed;
   return Math.round((used / 1024 / 1024) * 100) / 100 + "M";
}

global.gc(); // 0 每次查询内存都先执行gc()再memoryUsage(),是为了确保垃圾回收,保证获取的内存使用状态准确

console.log(usedSize()); // 1 初始状态,执行gc()和 memoryUsage()以后,heapUsed 值为 4M
var map = new WeakMap();
var a = new Array(10 * 1024 * 1024);

map.set(a, 1);

global.gc();
console.log(usedSize()); // 2 在 Map 中加入元素a,为一个 10*1024*1024 的数组后,heapUsed为83.88M左右

a = null;
global.gc();

console.log(usedSize()); // 3 将a置为空以后,heapUsed 变成了3.85M左右,说明WeakMap中的那个长度为5*1024*1024的数组被销毁了

image.png

这个时候,只要外部的引用消失,weakMap内部的引用a已经被垃圾回收清除,因此weakMap结构有助于防止内存泄露