Set
- Set 是 ES6 提供的构造函数,能够造出一种新的存储数据的结构
- 只有属性值,成员值唯一
- 可以转成数组,其本身具备去重,交集,并集,差集的作用
Set 只有属性值
// 括号里面可以存放支持迭代接口的值 有 symbol(symbol.inerator) 就属于迭代接口
let a = new Set([[1,2,3,4], 33, true,{name: 'ccc'}] );
console.log(a)
// set(4) { [1,2,3,4], 33, true,{name: 'ccc'}}
可以看到 a 打印出来只有属性值,没有属性名。
Set 成员值唯一
let a = new Set([[1,2,3,4], 33, true,{name: 'ccc'},33, 1] );
console.log(a)
// 输出 set(5) { [1,2,3,4], 33, true,{name: 'ccc'},1}
let b = new Set("qwerert")
// 输出 set(5) { 'q','w','e','r','t'}
上面的代码中我们可以看到在括号里面有两个 33, 但是输出出来的只有 1 个。33 自动去重了。在就是字符串的时候会拆分成一个一个值,也会默认去重。
Set 的增删查
Set 不能修改
// 增
let a = new Set([1] );
a.add([1,2]);
a.add(true);
a.add(true);
console.log(a)
// 输出 set(3) { 1, [1, 2], true} 在添加值的时候也可以进行去重
// 删
a.delete(true);
a.delete(1);
// 删除数组要用一个变量去记住删除数组的值
const b = [1,2];
a.delete(b);
a.clear(); // 清空了 a
// 查 使用 has()
// 可以直接打印全部值
a.has(1); // 如果有值返回 true 没有值返回 false
循环 Set
可以使用 forEach
方法或者 for...of...
方法(还是要迭代接口)
let a = new Set([[1,2,3,4], 33, true,{name: 'ccc'},33, 1] );
a.forEach(ele =>{
console.log(ele)
})
// [1,2,3,4],
// 33,
// true,
// {name: 'ccc'},
// 33,
// 1
for(let prop of a) {
console.log(prop)
}
// [1,2,3,4],
// 33,
// true,
// {name: 'ccc'},
// 33,
// 1
日常使用
// 数组转 Set
let arr = [1,2,3,4];
let s = new Set(arr);
// Set 转数组
console.log(Array.from(s));
console.log([...s]);
// 都输出 [1,2,3,4]
上面就是数组转 Set 和 Set 转数组的例子
在 ES5 中我们一般去重
const arr = [1,2,3,4,5,66,66,2,3];
let obj = {};
let newArr = [];
for ( let i = 0; i<arr.length; i++){
if(!obj[arr[i]]){
newArr.push(arr[i]);
obj[arr[i]] = true;
}
}
console.log(newArr);
// 输出 [1,2,3,4,5,66]
我们修改一下上面的代码
const o = {name:'ccc'}
const arr = [1,2,3,4,o,5,66,{name:'xxx'},o,66,2,3];
let obj = {};
let newArr = [];
for ( let i = 0; i<arr.length; i++){
if(!obj[arr[i]]){
newArr.push(arr[i]);
obj[arr[i]] = true;
}
}
console.log(newArr);
// 输出 [1,2,3,4,5,{name:ccc},66]
这里就会出现问题,在去重之后的数组中 name
的属性值明明不一样但是它还是给去重掉了。是因为在 arr[{}] = 1
的时候它是括号中是期望一个字符串,会默认给你调用原型链上的 Object.prototype.toString
方法,就是 arr[{}.toString] = 1
而 toString
方法可以把数据类型给输出出来
let o = {name:'ccc'};
o[{}] = 1;
// 默认调用 Object.prototype.toString 等同于
o[{}.toString] = 1
console.log(o)
// 输出 {name: 'ccc', [object object]: 1}
// 这个对象明显不是和前面同一个但是还是默认给你 [object object]
o[{name: 'xxx'}] = 2;
// 输出 {name: 'ccc', [object object]: 1}
如果使用 Set 就没有这方面的问题
let o = {name:'ccc'}
let arr = [1,2,3,4,o,5,66,{name:'xxx'},o,66,2,3];
let newArr= new Set(arr)
console.log([...newArr])
// 输出 [1,2,3,4,{name:ccc},5,{name:xxx},66]
并集、交集和差集
let arr1 = [1,2,3,4,5];
let arr2 = [4,5,6,7,8];
// 并集
let arr3 = new Set([...arr1,arr2])
console.log(arr3)
// 输出 [1,2,3,4,5,6,7,8]
// 交集
let a = new Set(arr2);
let arr4 = arr1.filter(ele=> a.has(ele))
console.log(arr4)
// 输出 [4,5]
// 差集
let a = new Set(arr1);
let b = new Set(arr2);
let c = [...a].filter(ele=> !b.has(ele));
let d = [...b].filter(ele=> !a.has(ele));
console.log([...c,...b]);
// 输出 [1,2,3,6,7,8]