16、Set

最后更新于:2022-04-02 06:07:27

  ES6引入了两种新的数据结构:Set和Map。Set是一组值的集合,其中值不能重复;Map(也叫字典)是一组键值对的集合,其中键不能重复。Set和Map都由哈希表(Hash Table)实现,并可按添加时候的顺序枚举。 ## 一、Set   Set类似于Array(数组),但需要通过SameValueZero算法保持值的唯一性。在前面的[第11篇](https://www.cnblogs.com/strick/p/10225168.html)中,曾讲到Object.is()依据的比较算法是SameValue,SameValueZero算法与之类似,唯一的区别就是在该算法中,+0和-0是相等的。 **1)创建**   要使用Set,需要先将其实例化,如下代码所示,其中构造函数Set()能接收一个可选的参数:可迭代对象,例如字符串、数组等。 ~~~ new Set();             //Set(0) {} new Set("abc");   //Set(3) {"a", "b", "c"} new Set([+0, -0, NaN, NaN]); //Set(2) {0, NaN} ~~~ **2)写入**   通过add()方法可以在Set的末尾添加一个任意类型的值,并且由于方法的返回值是当前的Set,因此可以采用链式的写法。再利用size属性就可得到成员数量,从而获悉是否添加成功,如下所示。 ~~~ var set = new Set(); set.add(1).add("a"); //Set(2) {1, "a"} set.size;      //2 ~~~   有一点需要注意,虽然Set有写入方法,但并没有对应的读取方法。 **3)移除**   总共有两个移除的方法,分别是delete()和clear()。delete()可指定移除的值,而clear()能清空集合,即移除所有成员。下面承接写入中的示例,分别调用这两个移除方法,并在其之后会根据has()方法判断是否移除成功。 ~~~ set.delete(1);    //Set(1) {"a"} set.has(1);   //false set.has("a"); //true set.clear();     //Set(0) {} set.has(1);      //false set.has("a");     //false ~~~ **4)遍历**   Set与数组一样,也有三个ES6新增的迭代器方法:keys()、values()和entries(),功能也相同。但由于Set没有键,只有值,因此keys()和values()返回的结果是相同的,如下所示。 ~~~ var digits = new Set(); digits.add(3).add(2).add(1); [...digits.keys()];      //[3, 2, 1] [...digits.values()]; //[3, 2, 1] [...digits.entries()]; //[[3, 3], [2, 2], [1, 1]] ~~~   除此之外,Set也有一个迭代方法:forEach(),参数也与数组的类似,第一个是回调函数,第二个是执行回调函数时使用的this对象。其中回调函数也包含3个参数,但参数含义略有不同,第一个和第二个都是当前成员的值,第三个是原始Set。从下面代码的注释中可知,Set的枚举顺序只与添加顺序有关,没有按照ES6所规定的枚举顺序(可参考[第11篇](https://www.cnblogs.com/strick/p/10225168.html))。 ~~~ /* 3 3 Set(3) {3, 2, 1} 2 2 Set(3) {3, 2, 1} 1 1 Set(3) {3, 2, 1} */ digits.forEach(function(value1, value2, set) { console.log(value1, value2, set); }); ~~~ **5)转换**   如果要将Set转换成数组,那么可以用Array.from()方法或扩展运算符实现,具体如下代码所示。注意,数组中的重复元素在传给Set后,就被过滤掉了。 ~~~ var duplicate = new Set([1, 1, {}, undefined]); Array.from(duplicate); //[1, {}, undefined] [...duplicate]; //[1, {}, undefined] ~~~ ## 二、WeakSet   WeakSet相对于Set,虽然只多了一个单词Weak(弱),但两者在很多方面都表现出了差异,具体如下所列:   (1)WeakSet中的值必须是对象,像数字、字符串或Symbol等其它类型都是不允许的。   (2)WeakSet中的对象都是弱引用,当没有变量或属性引用该对象时,将会被GC(Garbage Collection)自动回收掉。   (3)不可枚举WeakSet中的对象,即WeakSet不包含forEach()、keys()、values()和entries()方法。   (4)无法获取WeakSet中的成员数量,即没有size属性。   WeakSet的创建、写入和移除,与Set类似,具体如下所示。 ~~~ var weak = new WeakSet(), arr = [1]; weak.add(arr); //WeakSet {[1]} weak.has(arr); //true weak.delete(arr); weak.has(arr); //false ~~~   目前,挖掘出的WeakSet用例并不多,比较经典的是用来存储DOM节点,当该节点从文档中被移除后,不必再担心引发内存泄露。 ***** > 原文出处: [博客园-ES6躬行记](https://www.cnblogs.com/strick/category/1372951.html) [知乎专栏-ES6躬行记](https://zhuanlan.zhihu.com/pwes6) 已建立一个微信前端交流群,如要进群,请先加微信号freedom20180706或扫描下面的二维码,请求中需注明“看云加群”,在通过请求后就会把你拉进来。还搜集整理了一套[面试资料](https://github.com/pwstrick/daily),欢迎浏览。 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2e1f8ecf9512ecdd2fcaae8250e7d48a_430x430.jpg =200x200)
';