在 ECMAScript 6 之前,能够应用数组来存储值,而 ECMAScript 6 新增了 Set
和 WeakSet
两种汇合类型。
Set
Set
汇合能够应用 new
来创立一个空集合:
const s = new Set();
也能够在创立 Set
时就初始化实例:
const s = new Set(["小赵", "小明", "小霞"]);
也能够在初始化 Set
实例时自定义迭代器。
const s = new Set({[Symbol.iterator]: function*() {
yield "小赵";
yield "小明";
yield "小霞";
}
});
能够应用 size
属性获取 Set
实例的数量。
初始化后,能够应用 has()
办法查问是否存在某元素:
s.has("小郑"); // false
能够应用 add()
办法增加元素:
s.add("小玲");
应用 delete()
办法删除元素,并返回一个 boolean
值,用来判断是否存在要删除的值:
s.delete("小明"); // true
应用 clear()
办法清空 Set
实例:
s.clear();
当然,Set
与 Map
相似,能够蕴含任何 JavaScript 数据类型作为值,并且应用了 SameValeZero
操作,应用严格对象相等的规范来查看值的匹配性。
const s = new Set();
// SameValueZero 查看意味着独立的实例不会抵触
alert(s.has(function() {})); // false
Set
提供一个 Iterator
来以插入的程序生成汇合内容,通过 values()
办法以及其别名办法 keys()
办法获取迭代器,也能够通过 Symbol.iterator
属性来获取:
const s = new Set(["小赵", "小明", "小霞"]);
s.values === s[Symbol.iterator] // true
s.keys === s[Symbol.iterator] // true
for (let value of s.values()) {console.log(value);
}
// 小赵
// 小明
// 小霞
for (let value of s[Symbol.iterator]()) {console.log(value);
}
// 输入同上
也能够将汇合转换为数组:
const s = new Set(["小赵", "小明", "小霞"]);
console.log([...s]); // ["小赵", "小明", "小霞"]
汇合也提供了 entries()
办法,依照插入程序返回所有元素的值的 [value, value]
数组,与 Map
类似,但这里的每个值的键和值相等。
也能够应用 forEach()
办法遍历汇合:
const s = new Set(["小赵", "小明", "小霞"]);
s.forEach((v1, v2) => console.log(`${v1} -> ${v2}`));
// 小赵 -> 小赵
// 小明 -> 小明
// 小霞 -> 小霞
WeakSet
WeakSet
也是 ECMAScript 6 新增的汇合,也是 Set
的子集,但同时,WeakSet
中的值没有被援用时,就会被 GC 回收。
这里,应用 new
关键字实例化空的 WeakSet
:
const ws = new WeakSet();
也能够在创立时就初始化,然而 WeakSet
的值只能是 Object
或者继承自 Object
的子类:
const val1 = {id: 1},
val2 = {id: 2},
val3 = {id: 3};
// 应用数组初始化弱汇合
const ws1 = new WeakSet([val1, val2, val3]);
如果应用非对象的值会抛出 TypeError
:
const ws2 = new WeakSet([val1, "BADVAL", val3]);
// TypeError: Invalid value used in WeakSet
typeof ws2;
这里之所以限度只能应用 Object
作为值,是为了保障只有通过值对象的援用能力获得值。如果容许原始值,就没方法辨别初始化时应用的字符串字面量和初始化之后应用的一个相等的字符串了。
初始化后的操作,也能够同 Set
一样,应用 add()
办法增加元素,has()
办法查问元素,delete()
办法删除元素。
弱值
WeakSet
与 Set
不同之处在于汇合中的值不被援用时,不会阻止 GC 回收。如下所示:
const ws = new WeakSet();
ws.add({});
add()
办法中增加一个新的元素,然而这个元素没有其它援用,所以该元素会被当作垃圾回收,成为一个空集合。但当 {}
元素被一个对象援用时,就不会被当作垃圾回收掉,如下所示:
const ws = new WeakSet();
const q = {v:{}};
ws.add(q.v);
下面的例子中,q.v
就不会成为 GC 回收的指标。然而,将最初一个援用捣毁掉,如将 q.v
指向 null
,GC 就能够把这个值清理回收。
不可迭代值
与 WeakMap
一样,WeakSet
中的值在任何时候也可能会被销毁,所以没有提供其迭代的能力。因而,也就不会在不晓得其对象援用的状况下从 WeakSet
中取到值。
利用
这里能够应用 WeakSet
将打上同一标签的元素存储起来,这样在当前的查问中就比拟不便,如打上禁用标签的 DOM
元素都存储在 WeakSet
中:
const des = new WeakSet();
const lb = document.querySelector('#login');
// 通过退出对应汇合,给这个节点打上“禁用”标签
des.add(lb);
这样,在 DOM
元素从 DOM
树中删除时,WeakSet
实例中的元素也会被 GC 回收,开释内存。
这里只所以没有应用 Set
是因为,在 DOM
树中删除后,Set
实例不会让 GC 回收该元素。
更多内容请关注公众号「 海人为记 」