Set
对象是值的集合, Set中的元素只会出现一次,即 Set 中的元素是唯一的,无论是基本类型还是对象引用。
let set = new Set([1, 1, '1', { name: 'zhang' }, [1, 2, 3]]);
console.log(set);//Set(4) {1, "1", {…}, Array(3)}
通过上面简单的定义我们可以发现几个问题:
Set 对象中的值的个数,类似数组length属性
let set = new Set([1, '1', { name: 'zhang' }, [1, 2, 3]]);
console.log(set.size);//4
在Set
对象尾部添加一个元素。返回该Set
对象。
let set = new Set(['a','b']);
console.log(set.add('c'));//Set(3) {"a", "b", "c"}
删除单个元素,返回值为boolean
类型
let set = new Set(['a','b']);
console.log(set.delete('b'));//true
console.log(set.delete('c'));//false
移除Set
对象内的所有元素,无返回值
let set = new Set(['a','b']);
console.log(set.clear());//undefined
检查元素是否存在,返回值为boolean类型
let set = new Set(['a','b']);
console.log(set.has('b'));//true
console.log(set.has('c'));//false
let set = new Set(['a','b']);
for (const item of set) {
console.log(item);//'a' 'b'
}
for (const item of set.keys()) {
console.log(item); // 'a' 'b'
}
for (const item of set.values()) {
console.log(item); // 'a' 'b'
}
for (const item of set.entries()) {
console.log(item); // ["a", "a"] ["b", "b"]
}
数组章节我们已经讲过转换方法有两种,点语法
和Array.form
静态方法,可以将set转换为数组,就可以使用数组的一些便捷方法。
let set = new Set(['a', 'b']);
console.log(Array.from(set));//["a", "b"]
console.log([...set]); //["a", "b"]
转换成数组后,使用数组的filter方法过滤set数据:
//使用数组方法,取小于3的数据
let set = new Set([1, 2, 3, 4, 5]);
set = new Set([...set].filter(item => item < 3));
console.log(set);//Set(2) {1, 2}
//使用set方法,同样取小于3的数据
let set1 = new Set([1, 2, 3, 4, 5]);
set1.forEach(item => {
if (item >= 3) {
set1.delete(item);
}
})
//或则
// for (const item of set1) {
// if (item >= 3) {
// set1.delete(item);
// }
// }
console.log(set1);
我们另一个用的比较多的就是,把数组转Set去除重复元素;当然这是指接收到的外部数据存在重复元素需要去重,如果是我们自己定义的话,可以直接定义为Set类型。
//外部传过来的数据
let arr = [1, 2, 3, 4, 5, 3, 1];
arr = [...new Set(arr)];
console.log(arr);//[1, 2, 3, 4, 5]
let arr1 = [1, 2, 3, 8, 9];
let arr2 = [2, 8, 5, 6];
//并集(即两个数组都存在的元素)
console.log(arr1.concat(arr2.filter(item => !arr1.includes(item))));//[1, 2, 3, 8, 9, 5, 6]
//交集(即两数组共同拥有的元素),以上实例交集为[2, 8]
console.log(arr1.filter(item => arr2.includes(item)));// [2, 8]
//差集(数组arr1中有,数组arr2中没有的元素)
console.log(arr1.filter(item => !arr2.includes(item)));// [1, 3, 9]
//补集(去除arr1和arr2中都有的元素之后的所有元素)
console.log(arr1.filter(item => !arr2.includes(item)).concat(
arr2.filter(item => !arr1.includes(item))
))//[1, 3, 9, 5, 6]
let set1 = new Set([1, 2, 3, 9]);
let set2 = new Set([2, 5]);
console.log(set1, set2)
//并集
console.log(new Set([...set1, ...set2]))//Set(5) {1, 2, 3, 9, 5}
//交集
console.log(new Set([...set1].filter(item => set2.has(item))))//Set(1) {2}
//差集
console.log(new Set([...set1].filter(item => !set2.has(item))))//Set(3) {1, 3, 9}
//补集
console.log(new Set([...set1].filter(item => !set2.has(item)).concat(
[...set2].filter(item => !set1.has(item))
)))//Set(4) {1, 3, 9, 5}
WeakSet 和 Set 类似,都是不重复的值的集合,但是和 Set 有两点不同:
即WeakSet 中对对象的引用不会被考虑进垃圾回收机制,即只要没有其他的对象引用该对象,则该对象就会被回收,而不管它在不在 WeakSet, (由于这个特性,所以 WeakSet 适合临时存放一组对象和跟对象绑定的信息)
3. WeakSet 没有size属性,没法遍历(故没有 forEach 方法)
因为 WeakSet 中有多少个成员取决于(没有其他对象对WeakSet成员的引用后)垃圾回收机制有没有运行,运行前后可能成员的个数是不一样的,而垃圾回收机制何时运行是不可预测的,所以 ES6 规定 WeakSet 不能被遍历
用于存储DOM节点,而不用担心这些节点从文档移除时会引发内存泄露
即可以用来避免内存泄露的情况
new WeakSet()
可生成一个实例WeakSet作为构造函数:可接收数组或类数组对象作为其参数:则数组的所有成员 都会自动成为 WeakSet 对象的成员
注:
(1) 数组的成员只能是对象(因为WeakSet的成员只能是对象)
(2) 成为 WeakSet 的成员的是数组的成员,而不是数组本身。
WeakSet 有三个方法:add, delete, hasWeakSet.prototype.add(value)
向WeakSet 实例添加一个成员WeakSet.prototype.delete(value)
清除 WeakSet 实例的指定成员WeakSet.prototype.has(value)
判断某个值是否在WeakSet 实例中,返回布尔值