随笔-Set和WeakSet的使用
Set构造函数
Set是一个构造函数或类,可以用来创建Set实例,Set构造函数支持传入一个实现了Iterable接口的对象,并自动迭代出该对象的所有非重复元素存入到Set实例中
const set1 = new Set()
const set2 = new Set([1,2,3]) // 数组对象是可迭代对象
const set3 = new Set('abc') // 字符串对象也是可迭代对象
function fn(){
const set4 = new Set(arguments) // 函数的arguments对象
console.log(set4)
}
const divs = document.querySelectorAll('div') // NodeList也是可迭代对象
const set5 = new Set(divs)
const lis = document.getElementsByTagName('li') // HTMLCollection也是可迭代对象
const set6 = new Set(lis)
如果new Set() 传入的不是一个可迭代对象,会报错
某对象是否可迭代 指的是 该对象上是否 [Symbol.iterator]属性,且该属性是指向一个工厂函数,该工厂函数返回一个迭代器对象。
迭代器对象是指有next方法的对象,next方法实现迭代能力。
Set原型上的属性和方法
Set原型上的实例属性包括:
size :set实例中元素个数
这里没有用length,而是用size,我们知道数组的长度就是数组元素的个数,但是set底层是哈希表,哈希表的长度不一定是哈希表上元素的个数
Set原型上实例方法包括:
Set add(ele) : 添加元素
boolean delete(ele) : 删除元素
undefined clear(): 清空元素
boolean has(ele) : 判断元素是否存在
可以发现上述方法都是基于元素本身操作,没有基于索引操作的,这是因为Set底层数据结构是哈希表。
add方法会去重添加,它判断元素相同的标准是 ===严格相等,但是对于NaN例外,另外add方法会返回set实例,这和数组的push以及unshift不同。
delete删除元素成功返回true,删除元素失败返回false(比如删除的元素不存在)
clear清空set实例中的所有元素,没有返回值,即返回undefined
has判断元素是否存在,存在返回true,不存在返回false,我们需要对比它和数组includes方法,或者indexOf、lastIndexOf方法的区别,在功能上没有区别,但是在性能上has要比includes和indexOf或lastIndexOf快
需要注意add添加数据,和new Set添加多个数据的区别
也就是说new Set传入一个可迭代对象的话,它底层会将可迭代对象的元素都迭代出来后添加到set中,而add传入一个可迭代对象,会直接当成一个元素添加到set中
forEach((item, index, set)=>{})
Set原型上还有一个forEach遍历方法,该方法语法和Array原型上的forEach一致,但是需要注意的是Set实例只有值,没有键。所以item和index值相同。
SetIterator keys(): keys方法本质是调用values方法
SetIterator values(): 返回set实例上所有的元素,返回值是一个迭代器对象
SetIterator enteries(): 返回set实例所有键值对(键值对表现为数组形式)
由于Set实例没有键,所以keys底层调用的是values,
![]()
entries返回键值对中键和值相同,这里返回都是迭代器对象,所以可以for...of迭代
需要注意的是for...of迭代出来的entries键值对是数组格式,键是数组第一个元素,值是数组第二个元素
另外Set本身也是一个可迭代对象,而Set的[Symbol.iterator]函数属性指向的是Set.prototype.values,
所以我们一般不直接使用set实例的keys(),values(),entries()方法获得迭代器对象,而是直接使用set实例来for...of
Set转Array
由于Set是一个可迭代器对象,所以可以使用展开运算符,将Set展开为数列添加到数组中
还可以使用Array.from,该方法可以将一个类数组对象或可迭代对象转为数组
还可以使用for...of来迭代set元素加入数组中,和扩展运算符类似
Array转Set
通过new Set(arr) 就可以将arr转为set
Set的应用
1、去重 (如收集用户输入关键词)
2、并集
3、交集
4、差集
const arr = [1,2,3,4,5]
const arr1 = [2,4,6,8,10]
function getUnion(arr,arr1) {
return [...(new Set([...arr, ...arr1]))]
}
function getIntersection(arr,arr1){
return arr.filter(item=>{
return new Set(arr1).has(item)
})
}
function getDiff(arr,arr1) {
return arr.filter(item=>{
return !new Set(arr1).has(item)
})
}
WeakSet是一个构造函数或类,可以用来创建WeakSet实例。
和Set相同的是:WeakSet实例存储的元素不能重复,判同标准和Set相同
和Set不同的是:WeakSet实例只能存储对象,不能存储简单类型数据,否则报错
需要注意的是:WeakSet构造函数在new时,可以传入一个可迭代对象,但是和Set一样,WeakSet将可迭代对象的元素都迭代出来存储到自身上,而此时若迭代的元素不是对象,则也会报错。
WeakSet和Set另一个不同点是
WeakSet对象对存储在它身上的元素对象的引用是弱引用
Set对象对存储在他身上的元素的引用是强引用
如果一个对象被强引用关联,则不会被垃圾回收
如果一个对象仅被弱引用关联,则可能会被垃圾回收。
而这决定了WeakSet对象不需要关注存储在自身上的对象的内存回收,因为WeakSet对象对它们都是弱引用,若它们只被WeakSet对象引用,则会在适当的时机自动被垃圾回收。
由于weakset实例上保存的其他实例随时可能被垃圾回收,很不稳定,所以weakset没有size属性,也没有keys(),values(),entries(),也没有forEach方法,自身也就不能迭代,所以weakset不是可迭代对象,也就不能for...of,或者扩展运算符。
WeakSet原型上只有add,delete,has三个方法,用于添加删除判断元素
那么WeakSet的应用是什么呢?
WeakSet相比较于Set的优点是:无需考虑存储在自身上的对象的回收,不会造成内存泄漏
而Set上存储的对象,只有在Set实例被回收,或者删除掉它时,才会被回收,否则可能会造成内存泄漏。
当我们需要保存某些大型对象时,如DOM元素,则推荐使用WeakSet,而如果使用Set有内存泄漏的风险
相关文章
- T-SQL之DECLARE,SET,PRINT语句[通俗易懂]
- 请简述list,set,map类型的集合的各自特点_list与set的区别
- vector中find函数用法_java中set的用法
- MySQL Error number: MY-011185; Symbol: ER_SEMISYNC_SLAVE_SET_FAILED; SQLSTATE: HY000 报错 故障修复 远程处理
- ORA-13664: A task-managed “SQL Tuning Set” already exists for task “string”. ORACLE 报错 故障修复 远程处理
- C++ STL学习之容器set和multiset (补充材料)详解编程语言
- 实现MySQL函数SET实现灵活应用(mysql函数set)
- Redis清空Set的一秒操作(redis清空set)
- MySQL 中SET的用法及其重要性(mysql中的set)
- MySQL中SET集合的使用方法及注意事项(mysql中set集合)
- 深入了解MySQL中的SET集合使用方法(mysql中set集合)
- MySQL中SET用法详解(mysql中set 用法)
- Redis中Set集合操作实战技巧(redis集合set操作)
- Redis限制SET长度妙用和管控(redis限制set长度)
- 操作使用Redis进行Set操作的实践(redis进行set)
- Oracle Set用法概述快速上手(oracle set用法)
- Oracle SET更新实现数据持续改进(oracle set更新)
- 利用Redis设置Set值的实现方法(redis设置set值)
- Redis中Set个数查询实战指南(redis查询set个数)