const s = new Set(); [2,3,5,4,5,2,2].forEach(x=>s.add(x)); for(let i of s){ console.log(i);//2 3 5 4 }
上面代码经过add()方法向Set结构加入成员,结果代表Set结构不会添加剧复的值。
Set函数能够接受一个数组做为参数,用来初始化。数组
//例子1 const set = new Set([1,2,3,4,4]); [...set];//[1,2,3,4] //例子2 const items = new Set([1,2,3,4,5,5,5,5]); items.size//5 //例子3 const set = new Set(document.querySelectorAll('div'));
上面代码中,例一和例二都是Set函数接受数组做为参数,例三是接受相似数组的对象做为参数。
上面代码也展现了一种去除数组重复成员的方法。数据结构
//去除数组的重复成员 [...new Set(array)] //去除字符串里面的重复字符 [...new Set('ababbc')].join('');//'abc' //下面代码向Set实例添加了两个NaN,可是只能加入一个。这代表在Set内部两个NaN是相等。 let set = new Set(); let a = NaN; let b = NaN; set.add(a); set.add(b); set // Set {NaN} //另外,两个对象老是不相等的。 let set = new Set(); set.add({}); set.size // 1 set.add({}); set.size // 2
Set结构的实例有如下属性。函数
-Set.prototype.constructor:构造函数,默认就是set函数。 -Set.prototype.size:返回Set实例的成员总数。
Set实例的方法分为两大类:操做方法和遍历方法。下面先介绍四个操做方法。this
-add(value):添加某个值,返回Set结构自己。 -delete(value):删除某个值,返回一个布尔值,表示删除是否成功。 -has(value):返回一个布尔值,表示该值是否为Set的成员。 -clear();清除全部成员,没有返回值。
下面这些属性和方法的示例以下:prototype
s.add(1).add(2).add(2); //注意2被加入了两次 s.size//2 s.has(1)//true s.has(2)//true s.has(3)//false s.delete(2); s.has(2)//false
下面是一个对比,看看在判断是否包括一个键上面,Object结构和Set结构的写法不一样。code
//对象的写法 const properties ={ 'width':1, 'height':1 }; if(properties[someName]){ //do something } //Set的写法 const properties = new Set(); properties.add('width'); properties.add('height'); if(properties.has(someName)){ //do something }
Array.from方法能够将Set结构转为数组。对象
const items = new Set([1,2,3,4,5]); const array = Array.from(items);
这就提供了去除数组重复成员的另外一种方法。接口
function dedupe(array){ return Array.from(new Set(array)); }; dedupe([1,1,2,3])//[1,2,3]
Set 结构的实例有四个遍历方法,能够用于遍历成员。ip
-keys():返回键名的遍历器。 -values():返回键值的遍历器。 -entries():返回键值对的遍历器。 -forEach():使用回调函数遍历每一个成员。
(1)keys(),value(),entries()
keys方法、values方法、entries方法返回的都是遍历器对象。因为Set结构没有键名,只有键值因此keys方法和values方法的行为彻底一致。element
let set = new Set(['red','green','blue']); for(let item of set.keys){ console.log(items);//red,grren,blue } for(let item of set.values){ console.log(item);//red,green,blue } for(let item of set.entries){ console.log(item) } //['red','red']['green','green']['blue','blue']
上面代码中,entries方法返回的遍历器,同时包括键名和键值,因此每次输出一个数组,它的两个成员彻底相等。
Set结构的实例默承认遍历,它的默认遍历器生成函数就是它的values方法。
Set.prototype[Symbol.iterator] === Set.prototype.values
这就意味着,能够省略values方法,直接用for...of循环遍历Set。
let set = new Set(['red','green','blue']); for(let x of set){ console.log(x); } //red green blue
(2)forEach()
Set结构的实例与数组同样,也拥有forEach方法,用于对每一个成员执行某种操做,没有返回值。
let set = new Set([1,4,9]); set.forEach((value,key)=>console.log(key+':'+value)) //1:1 4:4 9:9
上面代码说明,foreach方法的参数就是一个处理函数。该函数的参数与数组的forEach一致,依次为键值、键名、集合自己。这里须要注意,Set结构的键名就是键值,所以第一个参数与第二个参数的值永远都是同样的。另外,forEach方法还能够有第二个参数,表示绑定处理函数内部的this对象。
(3)遍历的应用
扩展运算符(...)内部使用for...of循环,因此也可使用Set结构。
let set = new Set(['red','green','blue']); let arr = [...set]; //['red','green','blue'] 扩展运算符和Set结构相结合,就能够去除数组的重复成员。 let arr = [3,5,2,2,5,5]; let unique = [...new Set(arr)] //[3,5,2]
并且,数组的map和filter方法也能够间接用于Set了。
let set = new Set([1,2,3]); set = new Set([...set].map(x=x>*2)); //返回set结构:{2,4,6} let set = new Set([1,2,3,4,5]); set = new Set([...set].filter(x=>(x%2)==0)); //返回Set结构:{2,4}
所以使用Set能够很容易地实现并集、交集、和差集。
let a = new Set([1,2,3]); let b = new Set([4,3,2]); //并集 let union = new Set([...a,...b]); //Set {1,2,3,4} //交集 let intersect = new Set([...a].filter(x=>b.has(x))); //set{2,3} //差集 let difference = new Set([...a].filter(x=>!b.has(x))); //Set{1}
Javascript的对象,本质上是键值对的集合,可是传统上只能用字符串看成键,这给它的使用带来了很大的限制。
const data = {}; const element = document.getElementById('myDiv'); data[element] = 'metadata'; data['[object HTMLDivElement]']//'metadata'
上面代码原意是将一个DOM节点做为对象data的键,可是因为对象只接受字符串做为键名,因此element被自动转为字符串[object HTMLDivElement].
为了解决这个问题,ES6提供了Map数据结构。他相似与对象,也是键值对的集合,可是键的范围不限于字符串,各类类型的值均可以看成键。也就是说,Object结构提供了字符串-值的对应,Map结构提供了值-值的对应,是一种更完善的Hash结构实现。若是你须要键值对的数据结构,Map比Object更合适。
const m = new Map(); const o = {p:'Hello World'}; m.set(o,'content'); m.get(o)//'content' m.has(o)//true m.delete(o)//true m.has(o)//false
上面代码使用Map结构set方法,将对象o看成m的一个键,而后又使用get方法读取这个键,接着使用delete方法删除这个键。
上面的例子展现了如何向Map添加成员。做为构造函数,Map也能够接受一个数组做为参数。该数组的成员是一个个表示键值对的数组。
const map = new Map([ ['name','张三'], ['title','Author'] ]); map.size//2 map.has('name')//true map.get('name')//张三 map.has('title')//true map.get('title')//Author
事实上,不只仅是数组,任何具备Iterator接口、每一个成员都是一个双元素的数组的数据结构都剋以看成Map构造函数的参数。也就是说,Set和Map均可以用来生成新的Map。
const set = new Set([ ['foo',1], ['bar',2] ]) const m1 = new Map(set); m1.get('foo')//1 const m2 = new Map([['baz',3]]); const m3 = new Map(m2); m3.get('baz')//3
上面代码中,咱们分别使用set对象和Map对象,看成Map构造函数的参数,结果都生成了新的Map对象。
若是对同一个键屡次赋值,后面的值将覆盖前面的值。
const map = new Map(); map.set(1,'aaa') .set(1,'bbb') map,get(1)//'bbb'
上面代码对键1连续赋值两次,后一次的值覆盖前一次的值。
若是读取一个未知的键,则返回undefined。
new Map().get('dsada')//undefined.
(1)size属性
size属性返回Map结构的成员总数。
const map = new Map() map.set('foo',true) map.set('bar',false) map.szie//2
(2)set(key,value)
set方法设置键名key对应的键值为value,而后返回整个map结构。若是key已经有值,则键值会被更新,不然就新生成该键。
const m = new Map() m.set('edition',6);//键是字符串 m.set(262,'standard');//键是数值 m.set(undefined,'nah');//键是undefined
set方法返回的是当前的Map对象,所以剋以采用链式写法。
let map = new Map() .set(1,'a') .set(2,'b') .set(3,'c')
(3)get(key)
get方法读取key对应的键值,若是找不到key,返回undefined。
const m = new Map(); const hello = function(){console.log('hello');}; m.set(hello,'Hello ES6')//键是函数 m.get(hello)//Hello ES6
(4)has(key)
has方法返回一个布尔值,表示某个键是否在当前Map对象之中。
const m = new Map(); m.set('edition',6); m.set('262','standard'); m.set(undefined,'nah'); m.has('edition')//true
(5)delete(key)
delete方法删除某个键,返回true,若是删除失败,返回false。
const m = new Map(); m.set(undefined,'nah'); m.has(undefined)//true m.delete(undefined); m.has(undefined);//false
(6)clear()
clear方法清除全部成员,没有返回值。
let map = new Map(); map.set('foo',true); map.set('bar',false); map.size//2 map.clear(); map.size//0;