先把标题问题解决了,再学习基础知识,知其前因后果。看段代码:
 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' -> falseconsole.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 存在3set.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 与数组的转换
 // 数组转为setvar arr = [1,2,3]var set = new Set(arr)
// set转为数组:Array.fromvar set = new Set()set.add(1).add(2)Array.from(set)  // [1,2]// set转为数组:扩展运算符var arr = [...set]  // [1,2]
   复制代码
 4. Set 的遍历
 //1. forEachvar 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)  // trueset.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 集合。
评论