Set/weakSet
Set
用于存储任何类型的唯一值,无论是基本类型还是对象引用。
- 只能保存值没有键名
- 严格类型检测如字符串数字不等于数值型数字
- 值是唯一的
- 遍历顺序是添加的顺序,方便保存回调函数
基本使用
对象属性最终都会转为字符串
const obj = {1: 'mkimq', '1': 'mkimq.com'}
console.log(obj) // {1: 'mkimq.com'}
const mk = {[obj]: 'web'}
console.log(mk[obj.toString()])
console.log(mk['[object Object]'])
使用数组作为初始值
const set = new Set(['mkimq', 'mkimq.com'])
Set 中是严格类型约束的,下面的数值1与字符串1属于两个不同的值
const set = new Set()
set.add(1)
set.add('1')
console.log(set)
使用 add 添加元素,不允许重复添加
获取数量
获取元素数量
const set = new Set(['mkimq', 'mkimq.com'])
set.size
元素检测
检测元素是否存在
const set = new Set(['mkimq', 'mkimq.com'])
set.has('mkimq')
删除元素
使用 delete 方法删除单个元素,返回值为boolean类型
const set = new Set(['mkimq', 'mkimq.com'])
set.delete('mkimq')
使用 clear 删除所有元素
const set = new Set(['mkimq', 'mkimq.com'])
set.clear()
数组转换
可以使用点语法 或 Array.form 静态方法将Set类型转为数组,这样就可以使用数组处理函数了
const set = new Set(['mkimq', 'mkimq.com'])
console.log([...set])
console.log(Array.from(set))
移除Set中大于5的数值
let mk = new Set('123456789')
mk = new Set([...mk].filter(item => item < 5))
console.log(mk)
去除重复
去除字符串重复
console.log([...new Set('mkimq.com')].join(''))
去除数组重复
console.log(...new Set([1, 2, 3, 4, 1, 2, 3, 4]))
遍历数据
使用 keys()/values()/entries() 都可以返回迭代对象,因为set类型只有值所以 keys与values 方法结果一致。
const set = new Set(['mkimq', 'mkimq.com'])
console.log(set.values())
console.log(set.keys())
console.log(set.entries())
可以使用 forEach 遍历Set数据,默认使用 values 方法创建迭代器。
为了保持和遍历数组参数统一,函数中的value与key是一样的。
const set = new Set(['mkimq', 'mkimq.com'])
set.forEach((item, key) => console.log(item, key))
也可以使用 forof 遍历Set数据,默认使用 values 方法创建迭代器
const set = new Set(['mkimq', 'mkimq.com'])
for (const iterator of set) {
console.log(iterator)
}
交集
获取两个集合中共同存在的元素
const mk = new Set(['mkimq', 'mkimq.com'])
const mk2 = new Set(['mkimq', 'https://www.mkimq.com'])
const arr = new Set(
[...mk].filter(item => mk2.has(item))
)
差集
在集合mk中出现但不在集合mk2中出现元素集合
const mk = new Set(['mkimq', 'mkimq.com'])
const mk2 = new Set(['mkimq', 'https://www.mkimq.com'])
const arr = new Set(
[...mk].filter(item => !mk2.has(item))
)
并集
将两个集合合并成一个新的集合,由于Set特性当然也不会产生重复元素。
const mk = new Set(['mkimq', 'mkimq.com'])
const mk2 = new Set(['mkimq', 'https://www.mkimq.com'])
console.log([...new Set([...mk, ...mk2])])
WeakSet
结构同样不会存储重复的值,它的成员必须只能是对象类型的值。
- 垃圾回收不考虑WeakSet,即被WeakSet引用时引用计数器不加一,所以对象不被引用时不管WeakSet是否在使用都将删除
- 因为WeakSet 是弱引用,由于其他地方操作成员可能会不存在,所以不可以进行forEach( )遍历等操作
- 也是因为弱引用,WeakSet 结构没有keys( ),values( ),entries( )等方法和size属性
- 因为是弱引用所以当外部引用删除时,希望自动删除数据时使用 WeakMap
声明定义
以下操作由于数据不是对象类型将产生错误
错误示范
new WeakSet(['mkimq', 'mkimq.com'])
new WeakSet('mkimq')
正确示范
// WeakSet的值必须为对象类型
new WeakSet([['mkimq'],['mkimq.com']])
// 将DOM节点保存到WeakSet
document.querySelectorAll('button').forEach(item => Wset.add(item))
基本操作
下面是WeakSet的常用指令
const weakSet = new WeakSet()
const arr = [1]
// 添加
weakSet.add(arr)
// 删除
weakSet.delete(arr)
// 检索判断
weakSet.has(arr)
垃圾回收
WeaSet保存的对象不会增加引用计数器,如果一个对象不被引用了会自动删除。
- 下例中的数组被 arr 引用了,引用计数器+1
- 数据又添加到了 mk 的WeaSet中,引用计数还是1
- 当 arr 设置为null时,引用计数-1 此时对象引用为0
- 当垃圾回收时对象被删除,这时WakeSet也就没有记录了
const mk = new WeakSet()
let arr = [1]
mk.add(arr)
console.log(mk.has(arr))
arr = null
console.log(mk)