在ECMAScript6之前,数组可以用来存储值,ECMAScript6新增了Set和WeakSet两种集合类型。SetSet集合可以使用new创建一个空集合:consts=newSet();或者在创建Set时初始化实例:consts=newSet(["小赵","小明","小夏"]);您还可以在初始化Set实例时自定义迭代器。consts=newSet({[Symbol.iterator]:function*(){yield"小赵";yield"小明";yield"小夏";}});您可以使用size属性来获取Set实例的数量。初始化完成后,可以使用has()方法查询某个元素是否存在:s.has("小郑");//false可以使用add()方法添加元素:s.add("小玲");使用delete()方法删除一个元素,返回一个布尔值判断是否有需要删除的值:s.delete("小明");//true使用clear()方法清除Set实例:s.clear();当然,Set与Map类似,它可以包含任何JavaScript数据类型作为值,并使用SameValeZero操作,该操作使用严格的对象相等性标准来检查值的匹配。consts=newSet();//SameValueZero校验表示独立实例不会冲突alert(s.has(function(){}));//falseSet提供了一个Iterator来按照插入的顺序生成集合内容,通过values()方法及其别名方法keys()方法可以获得迭代器,也可以通过Symbol.iterator属性获取:consts=newSet(["小赵","小明","小夏"]);s.values===s[Symbol.iterator]//trues.keys===s[Symbol.iterator]//truefor(letvalueofs.values()){console.log(value);}//小赵//小明//小霞for(letvalueofs[Symbol.iterator]()){console.log(value);}//输出同上,集合也可以转换放入数组:consts=newSet(["小赵","小明","小夏"]);控制台日志([...s]);//["小赵","小明","小夏"]集合也提供了entries()方法,返回[value,value]数组中所有元素的值按插入顺序排列,类似Map,但是这里每个value的key和value是相等的。也可以使用forEach()方法遍历集合:consts=newSet(["小赵","小明","小夏"]);s.forEach((v1,v2)=>console.log(`${v1}->${v2}`));//小赵->小赵//小明->小明//小夏->XiaoXiaWeakSetWeakSet也是ECMAScript6中新增的集合,也是Set的子集。但同时,当WeakSet中的值没有被引用时,会被GC回收。在这里,使用new关键字来实例化一个空的WeakSet:constws=newWeakSet();也可以在创建时初始化,但是WeakSet的值只能是Object或者继承自Object的子类:constval1={id:1},val2={id:2},val3={id:3};//使用数组初始化弱集constws1=newWeakSet([val1,val2,val3]);如果使用非对象值,将抛出TypeError:constws2=newWeakSet([val1,"BADVAL",val3]);//TypeError:InvalidvalueusedinWeakSettypeofws2;这里之所以只能使用Object作为值,是为了保证只引用值对象来获取值。如果允许原始值,将无法区分初始化时使用的字符串文字和初始化后使用的等效字符串。初始化后的操作也可以和Set一样,使用add()方法添加元素,使用has()方法查询元素,使用delete()方法删除元素。弱值WeakSet与Set不同的是,当set中的值没有被引用时,不会阻止GC回收。如下图:constws=newWeakSet();ws.add({});在add()方法中添加了一个新元素,但是这个元素没有其他引用,所以这个元素会被当作垃圾回收,变成一个空集合。但是当{}元素被对象引用时,它不会被垃圾回收,如下所示:constws=newWeakSet();constq={v:{}};ws.add(q.v);在上面的例子中,q.v不会成为GC收集的目标。但是,如果最后一个引用被销毁,比如将q.v设置为null,GC可以清理回收这个值。不可迭代的值和WeakMap一样,WeakSet中的值随时可能被销毁,所以没有迭代的能力。因此,不可能在不知道其对象引用的情况下从WeakSet中获取值。在这个应用中,可以使用WeakSet来存储标记相同标签的元素,更方便以后的查询。例如,所有标有禁用标签的DOM元素都存储在WeakSet中:constdes=newWeakSet();constlb=文档。querySelector('#login');//通过添加相应的集合将此节点标记为“已禁用”des.add(lb);这样,当DOM元素从DOM树中删除时,WeakSet实例中的元素也会被删除GC回收,释放内存。这里没有使用Set的唯一原因是,Set实例在DOM树中被删除后,将不允许GC回收该元素。更多内容请关注公众号《海人的故事》
