在我们进入在WeakSet的使用之前,我们先来看一个用Set来存储对象引用的例子:
let set = new Set();
let key = {};
set.add(key);
key = null;
console.log(set.size); // 1
console.log([...set][0]); // {}
以上代码,我们存储了一个对象的引用key,但是随后我们通过key = null
清楚了对象的引用,但是随后我们查看set.size依然得到1,且依然可以通过把set展开到数组取到原本已经被我们清除了引用的key。
之所以会出现这样的结果是因为,Set存储的是对象的强引用,虽然在代码的其他地方已经不存在对此变量的引用,但是javaScript的垃圾回收机制依然不会回收这段地址。这种情况,就会造成我们常说的内存泄漏。
而WeakSet就是为了解决上面的问题而存在的,相比Set,WeakSet存的是对象的弱引用。意思就是,如果在代码的其他地方已经不存在任何引用,那么WeakSet也不会再保留这个引用,这样就可以被垃圾回收了。
了解了以上WeakSet的存在背景,现在就来看一下WeakSet的一些特性和使用:
一:初始化WeakSet
一:通过new WeakSet()初始化
let weakSet = new WeakSet();
二:传入可迭代对象初始化
let key1 = {};
let key2= {};
let weakSet = new WeakSet([key1, key2]);
二:WeakSet的add(),delete(),has()方法
区别于Set,WeakSet只有三个方法可用,分别是
1: add() 添加一个元素
2: delete() 删除一个元素
3: has() 查询某个元素是否存在
它们的功能和用法与Set所对应的三个方法一致,只是在参数类型上有所限制,即:
以上三个方法都不能传入基本数据类型,只能传入对象类型。 我们先来看一下代码示例:
let key1 = {name: 'may'};
let key2= {name: 'april'};
let weakSet = new WeakSet([key1, key2]);
console.log(weakSet.has(key1)); // true
weakSet.delete(key2);
let key3 = {name: 'mike'};
let result = weakSet.add(key3);
console.log(result);
最后打印 console.log(result)
,我们得到结果:
WeakSet {{…}, {…}}
__proto__: WeakSet
[[Entries]]: Array(2)
0:
value: {name: "may"}
1:
value: {name: "mike"}
length: 2
可以看到因为调用delete(key2)
, 所以我们最后的结果里面没有了key2。
三:WeakSet与Set的区别
WeakSet与Set除了存储的分别是对象的弱引用和强引用之外,还有很多差别,下面我们就来总结一下WeakSet的特性:
1: WeakSet只能不能存储基本数据类型。这几意味着,在初始化和调用add()的时候,都只能传入对象类型的元素。
2: 如果给add()方法传入非对象类型,会抛出错误。给delete()和has()传入非对象类型参数,则总是返回false。
3: WeakSet不可迭代,所以所有迭代的场景都不能使用,例如for-of, 展开运算符等
4: WeakSet不暴露任何的迭代器,例如keys(),values(),这也是其不能被迭代的原因
5: WeakSet不支持forEach()方法
6: WeakSet不支持size属性
以上就是关于WeakSet的基本特性和功能。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。