ES6学习笔记13:Map,Set,Weak Map和Weak Set

Map

与其他常见语言中的Map类似,Map是一系列键值对的集合,以下是一些常用特性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 外层函数
// 定义一个Map
let map = new Map();
map.set(1, 'val1');
map.set('2', {});
map.set({}, {k: 'v'});
/*
* 或者直接在构建时指定一些初始键值
* let map = new Map([[1, 'val1'],['2', {}],[{}, {k: 'v'}]]);
*/
// 获取指定键的值
map.get(1); 'val1'
// Map的循环,forEach函数或者使用for...of
map.forEach((val, key) => {
console.log(`Key ${key}: Value ${val}`);
});
for(let ent of map) {
console.log(`Key ${ent[0]}: Value ${ent[1]}`);
}
// entries() 获取所有键值对
// keys() 获取所有键
// values() 获取所有值
// has(k) 检查是否有键k的存在,存在返回true,否则返回false。
// delete(k) 删除键为k的键值对
// clear() 清楚所有键值对
// size 含有键值对的数量

Set

与其他常见语言中的Set类似,Set是不含重复值的集合,以下是一些常用特性。

1
2
3
4
5
6
7
8
9
10
11
// 定义一个Set
let set = new Set();
set.add(1);
set.add('2');
set.add({});
/*
* 或者直接在构建时指定一些初始键值
* let set = new Set([1, '2', {}]);
*/
// 循环也采用forEach()方法或者使用for...of
// 其他方法也与Map类似(除键值操作的方法外)

注意Set是不含重复值的,如果出现了两个重复值,则set中只会保留一个,但是如果是两个相同内容不同引用的对象则可以重复存在,但如果两次添加相同引用的对象,又只会保留一个。请看下面示例。

1
2
3
4
5
6
7
8
9
10
// 定义一个Set
let set = new Set([1, 2, 2, {}, {}]);
console.log(set.size); // 4
// 上面个的两个2,只存一次,但最后存储的两个对象,虽然内容一样,但是确实不同的对象,因此两个都保存着。
// 接着上面的示例。
let o = {};
set.add(o);
set.add(o);
console.log(set.size); // 5
// 虽然这次添加了两次,但是都是同一个对象,因此size只+1。

Weak Map

顾名思义,这个Weak Map是一个「弱」Map,这个「弱」指的是Weak Map对键的弱引用,其键(一定是对象)能够被GC回收。

首先Weak Map的键只能是对象,而不能是数字,字符串等其他类型;
其次,类型为对象的Weak Map的键是可以被GC回收的,也就是说当没有其他变量继续引用这个键的时候,该键在特定时候会被回收掉,当然Weak Map中也就不存在这个键了(实际上当外部已经不存在某个键的引用时,就永远无法访问到该键值对了,所以它必须被GC回收);
最后,Weak Map不能被循环,也没有如下方法:entries()keys()values()forEach()clear()

Weak Set

类似于Weak Map,Weak Set同样只接受对象,同样没有被引用的情况下会被GC回收,同样不能循环。

对比

Map、Set和Weak Map、Weak Set的主要区别。

类型 存储object以外的类型 无其他引用GC将回收 可循环
Map/Set
WeakMap/WeakSet

知识点总结

  1. 熟悉四者的基本概念;
  2. 熟悉Map/Set和WeakMap/WeakSet之间的区别和联系;
  3. 熟练使用相应的API。

参考

  1. BabelJS - Learn ES2015
  2. ES6 — set, map, weak Let’s talk about ECMAScript 2015 - Maciej Rzepiński
  3. ES6 WeakMaps, Sets, and WeakSets in Depth - Nicolás Bevacqua