先把标题问题解决了,再学习基础知识,知其前因后果。看段代码:
var obj = {a:1}
var set = new Set()
set.add(obj)
// 移除原始引用
obj = null
// 输出:1,说明set中还是存在值,是不是null?
console.log(set.size())
// 取出值看看 输出:div#set,并不是null
[...set][0]
复制代码
例子中变量 obj=null 时,便清除了对初始对象的引用,但是 Set 集合确保留了这个引用,这里可以通过展开运算符获取到引用值。也是因为 Set 集合对 obj 引用的存在,当 obj=null 时,垃圾回收机制就不能释放初始变量 obj 指向的对象内存空间。倘若你想让其他引用不再存在时,Set 集合中的这些引用也随之消息,就需要使用 Weak Set 集合,它是一种弱引用 Set 集合,只存储对象的弱引用,并且不可以存储原始值;集合中的弱引用如果是对象唯一的引用,则会被回收并释放相应内存。
var obj = {a:1}
var weakSet = new WeakSet()
weakSet.add(obj)
// 清除引用
obj = null
// {} weak set中的引用也被删除
console.log(weakSet)
复制代码
回答完了问题,再看看相应的使用方法。
Set 集合
Set 是一种有序列表,其中包含的是一些相互独立的非重复值,通过 Set 可以快速访问其中的数据,更有效的追踪各种离散值。
Set 本身是一个构造函数,可以接受一个数组或者类数组对象作为参数。下面看看它的属性和函数:
属性
Set.prototype.constructor: 构造函数
Set.prototype.size: 返回实例的成员总数
方法
Set.prototype.add(value):添加一个值,返回 Set 结构本身
Set.prototype.delete(vallue):删除某个值,返回布尔值
Set.prototype.has(value):返回布尔值,表示是否是成员
Set.prototype.clear():清楚所有成员,无返回值
用法
1. add 详解
add 添加新值,与原有值比较采用的是严格相等("==="),只有不等的才能添加到 Set 实例中。其中有个例外:NaN,因为 NaN 与 NaN 在严格相等比较下是不相等的,但 Set 里面只能有个 NaN。
var set = new Set()
set.add(1)
set.add('1')
set.add(1)
// 1==='1' -> false
console.log(set) // Set(2) {1, "1"}
// NaN值
var set1 = new Set()
set1.add(NaN)
set1.add(NaN)
console.log(set1) // Set(1) {NaN} 添加了2个NaN,但输出只有1个
// 其他几种常规方法
var set = new Set([1,2,3,4])
set.delete(1) // true 删除成功,此时set:{2,3,4}
set.has(3) // true 存在3
set.size() // 3,删除了1个元素
set.clear() // 清除集合所有元素,set:{}
复制代码
2. 数组去重
// 一维数组去重
var arr = [1,1,2,2,3]
var set = new Set(arr)
console.log(set) // {1,2,3}
// 多数组合并去重
var arr1 = [1,2,3]
var arr2 = [1,2,3]
var set1 = new Set([...arr1,...arr2])
console.log(set1) // {1,2,3}
复制代码
3. Set 与数组的转换
// 数组转为set
var arr = [1,2,3]
var set = new Set(arr)
// set转为数组:Array.from
var set = new Set()
set.add(1).add(2)
Array.from(set) // [1,2]
// set转为数组:扩展运算符
var arr = [...set] // [1,2]
复制代码
4. Set 的遍历
//1. forEach
var set = new Set([1,3,'ha'])
set.forEach((item,idx)=>{
console.log(item,idx)
})
//输出:
// 1 1
// 3 3 3
// 3 ha ha
// 说明:传统forEach函数的第二个值是索引,但Set是键值对的集合,第二个参数表示键,实际上与第二个参数相同
// 2. keys 返回键名的遍历器
for(let item of set.keys()){
console.log(item)
}
// 3. values 返回键值的遍历器
for(let item of set.values()){
// Set的键和值是相等的,所以keys和values返回的值是一样的
console.log(item)
}
// 4. entries() 返回键值对的遍历器
for(let item of set.entries()){
console.log(item) // 输出的是[key,value]
}
复制代码
Weak Set 集合
方法
支持 add()、has()和 delete()三个方法。例子如下:
var set = new WeakSet()
var obj = {a:1}
set.add(obj) // 返回set实例
set.has(obj) // true
set.delete(obj) // true,此时set:{}
set.add(1) // 报错:TypeError: Invalid value used in weak set
复制代码
其他
Weak Set 集合不可迭代,不能被 for-of 循环。
Weak Set 集合不暴露任何迭代器,所以无法通过程序本身检测其中内容
Week Set 集合不支持 forEach 方法
Week Set 集合不支持 size 属性。
Weak Set 看似功能受限,实际上是为了让它能够正确的处理内存中的数据。
总结
至此学习了 Set 和 Weak Set 集合的使用,以及为啥有 Weak Set 集合。下一章学习 ES6 的 Map 集合。
评论