ES6提供了心得数据结构——Set。它类似于数组,但是成员的值都是唯一的,没有重复。Set本身是一种构造函数,用来生成Set数据结构。
一、Set的基本用法。.
1、通过add向set结构添加数据成员,set不会添加重复的值。可以用来去除数组的重复元素,例如:new Set([1,2,3,3,3])。
const s = new Set();
[1,2,3,4,5,6,6].forEach(x => s.add(x));
for(let i of s){
console.log(i); //1,2,3,4,5,6
}
2、Set函数接受一个数组(或其他具有Iterable接口的其他数据结构)作为参数,用来初始化。
//用数组作为参数
const set = new Set([1,2,3,4,4]);
console.log([...set]); //[1,2,3,4]
//用类似于数组的对象作为参数
function divs(){
return [...document.querySelectorAll('div')];
}
const set = new Set(div());
console.log(set.size); //56
3、向Set加入值时不会发生类型转换,所以5和"5"是两种不同的值。Set内部判断两个值是否相同时,使用的算法是“Same-value equality",它类似于(===)。主要区别是NaN等于自身,而(===)认为NaN不等于自身。
let set = new Set();
let a = NaN;
let b = NaN;
set.add(a);
set.add(b);
console.log(set); //Set{ NaN }
向Set中添加了两个NaN,但是只输出了一个NaN,说明在Set内部,两个NaN是相等的。
4、两个对象总是不相等。
let set = new Set();
set.add({});
console.log(set.size); //1
set.add({});
console.log(set.size); //2
//由于两个空对象不是精确值,所以它们被视为两个值
二、Set实例的属性和方法。
1、Set结构的实例有以下属性。
- Set.prototype.constructor:构造函数,默认就是Set函数。
- Set.prototype.size:返回Set实例的成员总数。
2、Set实例的操作方法(用来操作数据的)。
- add(value):添加某个值,返回Set本身。
- delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
- has(value):返回一个布尔值,表示参数是否是Set的成员
- clear():清除所有成员,没有返回值。
3、Array.from方法可以将Set结构转换为数组。这就提供了一种去除数组重复元素的方法。
const items = new Set([1,2,3,4,5]);
const array = Array.from(items);
三、遍历操作。
1、Set结构的实例的四种遍历方法。
- keys():返回键名的遍历器
- values():返回键值的遍历器
- entries():返回键值对的遍历器
- forEach():使用回调函数遍历每个成员
注意:Set的遍历顺序就是插入的顺序。
2、keys()、values()、entries()方法返回的都是遍历器对象,由于Set结构没有键名,只有键值,所以keys和values方法的行为完全一致。
let set = new Set(["red","yellow","green"]);
for(let item of set){
console.log(item); //red yellow green
}
for(let item of set.keys())
{
console.log(item); //red yellow green
}
for(let item of set.values())
{
console.log(item); //red yellow green
}
for(let item of set.entries())
{
console.log(item);//[ 'red', 'red' ] [ 'yello', 'yello' ] [ 'green', 'green' ]
}
3、可以省略values方法,直接使用for....of循环遍历Set。
let set = new Set(["red",'green','blue']);
for(let x of set){
console.log(x); //red green blue
}
4、forEach()用于对每个成员执行某种操作,没有返回值。它有一个参数,就是一个处理函数,该处理函数有三个参数,依次是键值、键名、集合本身。
let set = new Set([1,2,3]);
set.forEach((value,key) => console.log(value*2)); //2 4 6
5、遍历的应用。
(1)扩展运算符(...)内部使用for...of循环,所以也可以用于Set结构。
let set = new Set(['red','green','blue']);
let arr = [...set];
console.log(arr); //[ 'red', 'green', 'blue' ]
(2)扩展运算符和Set结构相结合就可以去除数组的重复成员。
let arr = [3,5,2,2,5,5];
let unique = [...new Set(arr)];
console.log(unique); //[3,5,2]
(3)而且,数组的map和filter方法也可以用于Set。
let set = new Set([1,2,3]);
set = new Set([...set].map(x => x*2));
console.log(set); //Set { 2, 4, 6 }
let set = new Set([1,2,3,4,5]);
set = new Set([...set].filter(x => (x%2) == 0));
console.log(set); //Set { 2, 4 }
(4)使用Set可以很容易的实现并集(Union)、交集(Intersect)、差集(Different)。
let a = new Set([1,2,3]);
let b = new Set([4,3,2]);
//并集
let union = new Set([...a,...b]);
console.log(union); //Set { 1, 2, 3, 4 }
//交集
let Intersect = new Set([...a].filter(x => b.has(x)));
console.log(Intersect); //Set { 2, 3 }
//差集
let Different = new Set([...a].filter(x => !b.has(x)));
console.log(Different); //Set { 1 }
(5)如果想在遍历操作中同步改变原来的Set结构,目前没有直接的方法,但有两种 变通的方法,一种是利用原来的Set结构映射出来一个新的结构,然后赋值给原来的Set结构;另一种是利用Array.from方法。
let set = new Set([1,2,3]);
set = new Set([...set].map(val => val * 2));
console.log(set); //Set { 2, 4, 6 }
let set = new Set([1,2,3]);
set = new Set([Array.from(set,val => val * 2)]);
console.log(set); //Set { [ 2, 4, 6 ] }