关于程序员:快速了解-ES6-的Set与WeakSet

7次阅读

共计 2317 个字符,预计需要花费 6 分钟才能阅读完成。

在 ECMAScript 6 之前,能够应用数组来存储值,而 ECMAScript 6 新增了 SetWeakSet 两种汇合类型。

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();

当然,SetMap 相似,能够蕴含任何 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() 办法删除元素。

弱值

WeakSetSet 不同之处在于汇合中的值不被援用时,不会阻止 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 回收该元素。

更多内容请关注公众号「 海人为记

正文完
 0