ES6 标准前,可选的集合类型有限,数组使用的又是数值型索引,经常用于队列和栈。ES6 新增 Set 集合和 Map 集合,开发者就可以使用它们作非数值型索引的集合。
Set 集合
基本操作
ES6 中 Set 类型是一种有序列表,含有相互独立的非重复值,通过 Set 集合有效地追踪各种离散值。
// 创建Set集合并添加元素
var set = new Set();
set.add(5);
set.add("5");
console.log(set.size); // 2
// 创建Set集合并初始化
var set = new Set([1,2,3]);
// 非重复性
var set = new Set([1,2,2,3,3]);
console.log(set.size); // 3
set.add(1); // 已有,添加不成功
console.log(set.size); // 3
// 检查集合是否含有指定元素
var set = new Set([1,2,3]);
console.log( set.has(2) ); // true
console.log( set.has(4) ); // false
// 移除元素
var set = new Set([1,2,3]);
console.log(set.size); // 3
set.delete(1); // 删除成功返回true
console.log(set.size); // 2
set.clear();
console.log(set.size); // 0
为 Set 集合添加元素时,5 和 "5" 可以作为两个独立元素存在的,引擎内部通过 Object.is() 方法来检测两个值是否一致(Object.is()方法是 ES6 对象扩展的功能)。注意:+0 和 -0 被认为是相等的。
构造函数可接受所有可迭代对象作为参数,数值、Set集合、Map集合都是可迭代的。
非重复性:构造函数会过滤重复的值,保持集合元素唯一性,添加已有元素的行为会被忽略。
移除元素:有两种方式,delete() 删除指定元素,clear() 清空集合元素。
forEach 方法
使用过数组都应该知道数组也有 forEach 方法,可以简化数组遍历过程,不需要自己写循环语句。ES6 为 Set 集合也添加同样的方法。
| 类型 | 数组 | Set集合 |
|---|---|---|
| forEach() 回调函数的参数 | 1.元素值 2.下标索引 3.数组本身 | 1.元素值 2.元素值 3.Set集合本身 |
由于 Set 集合没有键名,ES6 标准委员会为了与数组的 forEach() 保持一致的三个参数,所以第一个参数与第二个参数相同,都能表示元素值。
var set = new Set([1,2,3]);
var fn = function (value){
console.log(value)
}
set.forEach( fn );
Set 集合转数组
数组转 Set 集合很简单,只需给 Set 构造函数传入数组即可;Set 集合转数组,通过 ES6 新增加的展开运算符(...)就可以轻松解决,展开运算符也可以将可迭代对象转换为数组。
// 数组转 Set集合
var array = [1,2,3,4];
var set = new Set(array);
console.log(set); // Set(4) [ 1, 2, 3, 4 ]
// Set集合转数组
var set = new Set([1,2,3]);
var array = [...set];
console.log(array); // Array(3) [ 1, 2, 3 ]
Weak Set 集合
Set 集合可以看作是一个强引用性的集合,如果我们存储的是对象的话,那 Set 集合就会强引用对象。如果这个对象被废弃,但是 Set 集合还引用了该对象,垃圾回收机制就不能释放该对象内存空间。
如果想要垃圾回收机制能处理对象,则首先要切断 Set 集合中对象的引用,才能再切断变量对对象引用。或者使用 clear() 清空,显然这是不理智的。
var object = {};
var set = new Set([object]);
console.log(set.size); // 1
set.delete(object);
console.log(set); // 0
object = null;
上面的代码能切断Set集合中对象的引用,但在操作麻烦,object置null前,要先用其切断Set对象引用。
ES6 早已为我们想好了解决的办法,就是另一种集合:Weak Set,它是一种弱引用的 Set 集合。Weak Set 集合只能用于存储对象,存储非对象程序抛出错误。
Weak Set 集合只支持3个方法:add()、has()、delete(),这三个方法与 Set 集合用法一致。
var weakSet = new WeakSet([1,{}]); // 抛出错误
var weakSet = new WeakSet([{}]);
weakSet.add(1); // 抛出错误
var object = {};
var weakSet = new WeakSet([object]);
object = null;
console.log(weakSet.size); // undefined,注意WeakSet没有这个属性
Weak Set 集合与 Set 集合的差别:
- Weak Set 保存对象弱引用且只能存储对象;
- Weak Set 只有add()、has()、delete()方法且不支持size属性;
- Weak Set 不可迭代、不暴露任何迭代器,所以 for-of、forEach() 无法使用。
Map 集合
Map 类型是一种存储许多键值对的有序列表。键名通过 Object.is() 方法实现键的唯一性。
基本操作
// 创建Map集合并添加键值对
var map = new Map();
map.set("key","value");
console.log(map.get("key")); // value
// 创建Map集合并初始化
var map = new Map([["key1","value1"], ["key2","value2"]]);
console.log(map.get("key1")); // value1
console.log(map.get("key2")); // value2
// 非重复性
var map = new Map([["key","value1"], ["key","value2"]]);
console.log(map.get("key")); // value2
// 检查集合是否含有指定的键
var map = new Map([["key1","value1"]]);
console.log( map.has("key1") ); // true
console.log( map.has("key") ); // false
// 移除键值对
var map = new Map([["key1","value1"], ["key2","value2"]]);
console.log(map.size); // 2
map.delete("key1"); // 删除成功返回true
console.log(map.size); // 1
map.clear();
console.log(map.size); // 0
Map 集合 has()、delete()、clear()方法都与 Set 集合用法类似。
Map 构造函数传入数组来初始化,数组每个元素都是一个子数组,包含键与值两个元素。
forEach 方法
Map 集合使用 forEach() 遍历过程,按照键值对插入 Map 集合的顺序来传入回调函数中。
| 类型 | 数组 | Map集合 |
|---|---|---|
| forEach() 回调函数的参数 | 1.元素值 2.下标索引 3.数组本身 | 1.对应值 2.键名 3.Map集合本身 |
Weak Map 集合
Weak Map 是弱引用 Map 集合,用于键名存储对象的弱引用。Map 集合中,对象可用作键名,键名强引用对象。其实 Weak Map 和 Map 之间的道理与 Weak Set 和 Set的类似,围绕都是对象弱引用与强引用。
ES6 规定 Weak Map集合是一种存储许多键值对的无序列表,列表键名必须是非 null 类型的对象。
var weakMap = new WeakMap([[1, "a"]]); // 抛出错误
var weakMap = new WeakMap();
weakMap.set(1,{}); // 抛出错误
var object = {};
var weakMap = new WeakMap([[object, { name:1 }]]);
object = null;
console.log(weakSet.size); // undefined,注意WeakSet没有这个属性
Weak Map 集合与 Map 集合的差别:
- Weak Map 键名保存对象弱引用且键名只能是对象;
- Weak Map 只有get()、set()、has()、delete()方法,但这些方法用法与 Map类似;
- Weak Map 不支持size属性;
- Weak Map 的 forEach() 方法无法使用。
相对 Map 集合而言,Weak Map 集合对用户的可见度更低。如果只用对象作为集合的键名,那么Weak Map 集合是最好的选择,通常保存一些对象的附加信息或私有数据。使用 Weak Map 有效避免内存泄漏的问题,优化内存使用。
如有错误,欢迎到评论区提出,谢谢。