一种新的数据结构
定义
同数组相似,数组中可能存在重复的值,但是Set中的值是唯一的不存在重复的值,它是一个伪数组
生成set实例
初始化一个空的Set
let s = new Set()
console.log(s); // []
放入初始化数据
let s = new Set([1,2,3])
console.log(s);
假如有重复的值呢?
// 输出的结果会忽略重复的值
let s = new Set([1,2,3,2])
console.log(s); // [1,2,3]
常用方法
添加数据
支持链式操作
let s = new Set([1,2,3,2])
s.add('lee').add('ES6')
console.log(s); // [1, 2, 3, 'lee', 'ES6']
删除数据
let s = new Set([1,2,3,2])
s.add('lee').add('ES6')
s.delete(2)
console.log(s); // [1, 3, 'lee', 'ES6']
清空数据
let s = new Set([1,2,3,2])
s.add('lee').add('ES6')
s.delete(2)
s.clear()
console.log(s); // []
判断Set中是否包含某个值
let s = new Set([1,2,3,2])
s.add('lee').add('ES6')
s.delete(2)
console.log(s.has('lee')); // true
获取Set的长度
let s = new Set([1,2,3,2])
s.add('lee').add('ES6')
s.delete(2)
console.log(s.size); // 4
遍历Set
forEach
let s = new Set([1,2,3,2])
s.add('lee').add('ES6')
s.forEach(item => console.log(item)) // 1 2 3 lee ES6
for of :遍历可遍历的对象
let s = new Set([1,2,3,2])
s.add('lee').add('ES6')
for(let item of s) {
console.log(item); // 1 2 3 lee ES6
}
for of keys() && for of values() && for of entries()
let s = new Set([1,2,3,2])
s.add('lee').add('ES6')
for(let item of s.keys()) {
console.log(item);
}
for(let item of s.values()) {
console.log(item);
}
====> 通过上面可以发现Set中的key和value的值是一样的
应用场景
1.数组去重
let arr = [1,2,3,4,2,3]
let s = new Set(arr)
console.log(s); // [1,2,3,4]
2.数组合并去重
通过Set去重,通过拓展运算符合并数组(拓展运算符就是将数组中的值取出来),得到的是Set,还需要对Set进行扩展或者使用Array.from()将Set变成数组
let arr1 = [1,2,3,4]
let arr2 = [2,3,4,5,6]
let s = new Set([...arr1,...arr2])
console.log([...s]); // [1,2,3,4,5,6]
console.log(Array.from(s)); // [1,2,3,4,5,6]
3. 数组的交集
let arr1 = [1,2,3,4]
let arr2 = [2,3,4,5,6]
// 数组的去重
let s1 = new Set(arr1)
let s2 = new Set(arr2)
// 数组的去重
let result = new Set(arr1.filter(item => s2.has(item)))
// 将Set转为数组
console.log([...result]); // [2,3,4]
4. 数组的差集
let arr1 = [1,2,3,4]
let arr2 = [2,3,4,5,6]
let s1 = new Set(arr1)
let s2 = new Set(arr2)
let r1 = new Set(arr1.filter(item => !s2.has(item)))
let r2 = new Set(arr2.filter(item => !s1.has(item)))
let r3 = [...r1,...r2]
console.log(r3); // [1,5,6]
Weakset
Weakset同Set有什么区别呢?
Weakset中只能存对象
let ws = new WeakSet()
console.log(ws.add(2)); // Ivalid value used in weak set
其他删除添加等方法同Set一样
let ws = new WeakSet()
ws.add({
name: 'lee'
})
ws.add({
age:5
})
console.log(ws);
删除对象的时候要注意下面这样删除对象是失败的,为什么?
// 删除失败
let ws = new WeakSet()
ws.add({
name: 'lee'
})
ws.add({
age:5
})
ws.delete({
name: 'lee'
})
console.log(ws);
add添加的对象和delete删除的对象虽然一样,但是实质上在堆内存中对应2块不同的内存空间
正确的删除方法是声明变量,将堆内存中的对象对应的栈内存地址存下来,对其进行增删操作,操作对象实际上就是操作这个内存地址
let ws = new WeakSet()
let obj1 = {
name: 'lee'
}
ws.add(obj1)
ws.add({
age:5
})
ws.delete(obj1 )
console.log(ws);
当然它也有has方法来判断WeakSet中是否存在某个对象
let ws = new WeakSet()
let obj1 = {
name: 'lee'
}
let obj2 = {
age:5
}
ws.add(obj1)
ws.add(obj2)
ws.delete(obj1 )
console.log(ws.has(obj2)); // true
WeakSet 不支持遍历
let ws = new WeakSet()
let obj1 = {
name: 'lee'
}
let obj2 = {
age:5
}
ws.add(obj1)
ws.add(obj2)
ws.forEach( item => console.log(item)) // ws.forEach is not a function
WeakSet中对这个对象是弱引用并不会被垃圾回收机制所考虑
WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于 WeakSet 之中。
弱引用和垃圾回收机制
弱引用:垃圾回收机制中是不考虑WeakSet对这个对象的引用
如果其他对象不再引用当前的对象的时候,那么垃圾回收机制就会自动回收这个对象所占用的内存空间
垃圾回收机制又叫GC,现在是计数的垃圾回收机制,当前的值被引用一次那么就+1,就是+1+1+1...
只要被引用的次数不为0,那么垃圾回收机制就不会回收这个变量,也就不会释放当前的内存
如果这个值一直被引用着,那么它就不会被垃圾回收,那么如果数量越来越多,就会引发内存泄漏
应用场景
WeakSet适用于临时存放对象,或者跟对象绑定一些相关的信息(当对象销毁后,WeakSet中对这个对象存值的引用也会自动的消失)