SE6新特性之集合Set、Map、WeakSet和WeakMap详解

来源:互联网 发布:linux换行符替换 编辑:程序博客网 时间:2024/05/17 07:49

SE5的时候我们经常用数组或者类数组对象来操作数据,而对于一些使用惯了java之类语言的集合的开发人员来说,总有少了点什么的感觉,SE6提供Set和Map这两个集合。不仅从根本上为一些问题提供了解决方案(如数据不重复),还大大提升了性能。

要想理解Set和Map,就要从它的根本问题说起,在进行详细的API概览之前,我觉得有必要先说明两点:

  • 遍历Set和Map的顺序就是元素插入的顺序。这是与其它语言最不一样的地方,之所以这样定是因为负责实现ES6集合模块的作者经过实验验证,在javaScript中确定顺序遍历比不确定遍历效率要高。
  • Set和Map没有hash码。在其他语言,都能够自行实现一个哈希函数并暴露出系统默认的哈希函数,但在javaScript委员会选择了不暴露 。
关于第二点可能有些难理解,我们通过一个例子来说明:
var a = {name:"Jhon"};var b = {name:"Jhon"};var set = new Set();set.add(a).add(b);console.log(set.size); //2//这两个对象应该按相同处理,毕竟它们有完全一样的属性。但在JavaScript中,它们是各自独立、互不相同的。

读万卷书不如操作一下,下面我就会对操作集合的这些API进行逐一的尝试验证,并且你会发现官方说明可能和浏览器实现是有差异的。

Set集合,没有重复元素的集合

var a = {name:"Jhon"};var b = {name:"Jhon"};var set = new Set(); // 创建一个新的,空的Setset.add(a).add(6); //添加两个元素,add返回集合自身,可以链式调用console.log(set[0]); //undefined,不支持索引遍历console.log(set.size); //打印元素个数 2set.forEach(function(value){  //遍历Setconsole.log(value); //Object { name: "Jhon" },6});if(set.has(a)){ //判断是否存在某个元素console.log("a"); //a}if(set.has(b)){ //falseconsole.log("b"); }if(set.has({name:"Jhon"})){ //falseconsole.log("other");}var c = [1,2,2,3,4];var setc = new Set(c); //new Set(iterable) :从任何可遍历数据中提取元素,构造出一个新的集合。console.log(setc.size); //4,元素去重console.log(setc.delete(4));//true,官方说delete会返回集合自身,但是在最新版火狐中如果元素存在,则返回true,反之返回false,链式调用会报出错console.log(setc.size); //3setc.clear(); //清空Setconsole.log(setc.size); //0//set.keys() 、 set.values() 和 set.entries() 返回各种迭代器,它们是为了兼容 Map 而提供的,所以我们待会儿再来看。


Map集合,由若干键-值对组成

var map = new Map(); //创建一个新的,空的Mapmap.set("one",1); //增加列表项map.set("two",2);console.log(map.size); //2,获取元素个数if(map.has("one")){ //true,判断元素存在console.log("one");}console.log(map.get("one")); //1,根据key获取元素map.forEach(function(value, key, map){ //遍历mapconsole.log(key + ":" + value); //one:1,two:2});for(var key of map.keys()){ //返回key的迭代器console.log(key); //one,two}for(var value of map.values()){ //返回值的迭代器console.log(value); //1,2}for(var [key,value] of map.entries()){ //返回项的迭代器console.log(value); //1,2}console.log(map.delete("one")); //true,根据key删除项map.clear(); //清空mapconsole.log(map.size); //0var a = [["one",1],["two",2]];var map1 = new Map(a); //new Map(pairs),通过数组或者已存在的map创建Mapmap1.forEach(function(value, key, map){ console.log(key + ":" + value); //one:1,two:2});


弱引用集合WeakSet和WeakMap

Map和Set都为内部的每个键或值保持了强引用,也就是说,如果一个对象被移除了,回收机制无法取回它占用的内存 ,除非在Map或者Set中删除它。

WeakSet并不对其中对象保持强引用。当WeakSet中的一个对象被回收时,它会简单地被从WeakSet中移除。WeakMap也类似地不为它的键保持强引用。如果一个键仍被使用,相应的值也就仍被使用 。
下面是弱引用集合的一些限制:
  • WeakMap只支持new、has、get、set 和delete。 
  • WeakSet只支持new、has、add和delete 。
  • WeakSet的值和WeakMap的键必须是对象。
  • 都不可迭代,除非专门查询或给出你感兴趣的键,否则不能获得一个弱集合中的项 。
以上就是ES6集合的操作以及注意事项。





0 0
原创粉丝点击