ES6提出了一个新的数据结构: set。和Python的set差不多,都是集合内不会出现重复的元素。这一趴就简单聊聊。
1, 声明
set是个构造函数,所以set的实例是引用数据类型,声明一个set需要用new运算符。
参数可以是一个数组或者伪数组
let arr = [1,1,2,2,3,4,5,5,6,7];
let oSet = new Set(arr);
// Set(7){1, 2, 3, 4, 5, 6, 7 }
由于set中的元素具有唯一性,所以set可以作为去重的方法来使用。
但是不要忘了,set不是array,如果后续需要做一些数组操作,则需要做一步转化。
let arr2 = [...oSet];
let arr3 = Array.from(oSet);
// 通常情况下我使用第一种方法来转化,两种方法的效率差不多。
size是set的属性,同array的length,用来记录实例中元素的个数。
let oSet = new Set();
for( let i = 0; i < 5; i++ ) {
oSet.add(i)
};
console.log(oSet.size); // 5
2,方法
set共有8种方法。
方法 | 作用 | 参数 | 返回值 |
---|---|---|---|
add(value) | 在set中添加一个值 | 要添加的值 | 返回set本身 |
delete(value) | 从set中删除一个值 | 要删除的值 | 返回一个布尔值,true为删除成功,false为失败。 |
has(value) | 在set中搜索一个值 | 要搜索的值 | 返回一个布尔值,true为set中有该值,false为没有。 |
clear() | 清空该set | 无 | 无 |
keys() | 用于遍历set中的键名 | 无 | 返回一个键名的遍历器 |
values() | 用于遍历set中的值 | 无 | 返回一个值的遍历器 |
entries() | 用于遍历set中的键值对 | 无 | 返回一个键值对的遍历器 |
forEach(callback()) | 用于使用回调函数遍历 | 回调函数 | 无 |
1 add(value)
该方法可以向set中添加一个元素, 该元素需要可迭代。
let func = function(){};
let oSet = new Set(func);
<!--
reg.html:23 Uncaught TypeError: function(){} is not iterable
如果传入函数 就会报错
-->
由于set中元素的唯一性,即使使用add方法传入多个相同值,也只会保留一个
let oSet = new Set();
for( let i = 0; i < 100; i++ ) {
oSet.add("a")
}
console.log(oSet.size); // 1
但是如果传入的是引用数据类型,则只会在set中储存指针。
let oSet = new Set();
for( let i = 0; i < 100; i++ ) {
oSet.add(new String("a"))
}
console.log(oSet.size); // 100
2 delete(value)
删除一个元素 返回一个布尔值,成功返回true 失败返回false
let arr = [1,1,2,2,3,4,5,5,6,7];
let oSet = new Set(arr);
console.log(oSet.delete(1)); // true
console.log(oSet.delete(1)); // false 由于唯一性 1 被删除后没有1了
3 has(value)
检索set,返回一个布尔值,如果set中有该元素则返回true,失败返回false
let oSet = new Set();
oSet.add({});
oSet.add("a");
console.log(oSet.has({})); // false 由于set中只保存指针 所以false
console.log(oSet.has("a")); // true
4 clear()
清空set
let oSet = new Set();
oSet.add("a");
console.log(oSet.size); // 1
oSet.clear();
console.log(oSet.size); // 0 set实例还在 但是被清空了
5 keys() & 6 values()
keys() values() 方法适用于遍历set。
但是有个问题 key的解构没有键值对。只有键值。所以keys()方法和value()方法返回的基本是一模一样的。
let oSet = new Set([1,1,2,2,3,4,5,5,6,7]);
console.log(oSet.keys()); // SetIterator {1, 2, 3, 4, 5, …}
console.log(oSet.values()); // SetIterator {1, 2, 3, 4, 5, …}
7 entries()
也是遍历set的,但是返回的是键值对(没有键还要返回键值对。。。。)
let oSet = new Set([1,1,2,2,3,4,5,5,6,7]);
for( let i of oSet.entries()){
console.log(i)
};
// [1, 1]
// [2, 2]
// [3, 3]
// [4, 4]
// [5, 5]
// [6, 6]
// [7, 7]
8 forEach(callback)
和数组的foreach一样,用来操作对实例中的元素进行操作
let oSet = new Set([1,1,2,2,3,4,5,5,6,7]);
oSet.forEach((val, key)=>{
console.log(`${key}:${val}`)
return val+1
})
// 1:1
// 2:2
// 3:3
// 4:4
// 5:5
// 6:6
// 7:7
console.log(oSet);
// Set(7) {1, 2, 3, 4, 5, …}
// forEach方法return值不会对set实例产生影响。
3,补充
除了set之外,还有一种新数据类型是WeakSet
WeakSet也具有唯一性,但是没有size属性,而且属于弱引用,元素在外部引用计数没有之后会被垃圾回收机制回收,不会考虑是否在WeakSet中被引用。因此
WeakSet不能被遍历!
所以也就没有那些遍历方法。
let oWeakSet = new WeakSet();
console.log(oWeakSet.forEach,oWeakSet.keys,oWeakSet.values,oWeakSet.entries);
// undefined undefined undefined undefined
WeakSet的构造函数,传的值需要是个数组或者其他可迭代对象,但是,如果只是传个数组,会报错。
let arr = [1,1,2,2,3,4,5,5,6,7];
let oWeakSet = new WeakSet(arr);
// Uncaught TypeError: Invalid value used in weak set
WeakSet()的参数不能是个一维数组。二维起步
let arr = [1,1,2,2,3,4,5,5,6,7];
let arr2 = [arr,[1,2],arr,[[1,2],[3,4,[5,6]]]];
let oWeakSet = new WeakSet(arr2);
console.log(oWeakSet);
// WeakSet {Array(2), Array(2), Array(10)}
// 由于WeakSet也有唯一性,所以arr只有一个
如果需要添加一个一维数组或者对象,则需要使用add(value)
let arr = [1,1,2,2,3,4,5,5,6,7];
let oWeakSet = new WeakSet();
oWeakSet.add(arr);
oWeakSet.add({});
console.log(oWeakSet);
// WeakSet {Array(10), {…}}
另外,WeakSet也有Set的其他方法
oWeakSet.add();
oWeakSet.delete();
oWeakSet.has();
返回的也和Set的同类方法一样。