WeakSet

JavaScript中的WeakSet是一个只存储对象且具有弱引用特性的集合。它不允许存储非对象值,且其成员不会影响垃圾回收机制,因此适用于临时存储和避免内存泄漏。WeakSet没有size属性和forEach方法,不支持遍历,常用于存放DOM节点或其他需要弱引用的场景,以确保对象在不再使用时能被正确清理。此外,WeakSet可以防止实例方法在非实例上被调用,提供了一种确保方法安全性的机制。
摘要由CSDN通过智能技术生成

WeakSet

weakSet结构与Set类似,也是不重复的值的集合。但是,它与Set有两个区别。
首先,WeakSet的成员只能是对象,而不能是其他类型的值。

const ws = new WeakSet();
ws.add(1)
// TypeError:Invalid value used in weak set
ws.add(Symbol())
// TypeError:invalid value used in weak set

当试图向Weakset添加一个数值和Symbol值时,会报错,因为WeakSet只能放置对象。
其次,WeakSet中的对象都是弱引用,即垃圾机制不考虑WeakSet对该对象的引用,也就是说,如果其他对象都不在引用该对象,那么垃圾回收机制会自动回收改对象所占用的内存,不考虑该对象话存在于WeakSet之中。

这是因为垃圾回收机制根据对象的可达性来判断回收,如果对象还能被访问,到垃圾回收机制就不会释放这块内存。结束使用该值之后,有时会忘记取消引用,导致内存无法释放,进而可能会引发内存泄露。WeakSet里面的引用,都不计入垃圾回收机制,所以就不存在这个问题。因此,WeakSet适合临时存放一组对象,以及存放跟对象绑定的信息。只要这些对象在外部消失,它在WeakSet里面的引用就会自动消失。

由于上面这个特点,WeakSet的成员是不适合引用的,因为它会随时消失。另外由于WeakSet内部有多少个成员,取决于垃圾回收机制有没有运行,运行前后很可能成员个数是不一样的,而垃圾回收机制何时运行是不可预测的,因此ES6规定WeakSet不可遍历。
WeakMap也具有以上特点。

语法

WeakSet是一个构造函数,可以使用new命令,创建WeakSet数据结构。

const ws = new WeakSet();

作为构造函数,WeakSet可以接受一个数组或类似数组的对象作为参数,(实际上,任何具有Interable接口的对象,都可以作为WeakSet的参数。)该数组的所有成员,都会自动成为WeakSet实例对象的成员。

const a = [[2,3],[3,4]];
const ws = new WeakSet(a);
// WeakSet{[1,2],[3,4]}

上面的代码中,a是一个数组,它有两个成员,都是数组。将a作为WeakSet构造函数的参数,a的成员会自动成为WeakSet的成员。

注意,是a数组的成员成为WeakSet的成员,而不是a数组本身。这意味着,数组的成员只能是对象。

const b = [3,4];
const ws = new WeakSet(b);
// Uncaught TypeError:Invalid value used in weak set(...)

上面的代码中,数组b的成员不是对象,加入WeakSet就会报错。
WeakSet有以下三个方法。
WeakSet.prototype.add(value):添加成员;
WeakSet.prototype.delete(value):清除实例的制定成员;
WeakSet.prottype.has(value):返回一个布尔值,表示某个值是否在WeakSet实例之中。

const ws = new WeakSet();
const obj = {};
const foo = {};
ws.add(window);
ws.add(obj);

ws.has(window); //true
ws.has(foo); //false

ws.delete(window);
ws.has(window); // false

WeakSet没有size属性和forEach属性,因为WeakSet不能遍历,是因为成员都是弱引用,随时可能取消,遍历机制无法保证成员的存在,很可能刚刚遍历结束,成员就取不到了。WeakSet的一个用处,是储存DOM节点,而不用担心这些节点从文档中移除,会随时引发内存泄露。

下面是WeakSet的另一个例子。

const foos = new WeakSet()
class Foo {
constructor() {
foos.add(this)
}
method () {
id(!foos.has(this)) {
throw new TypeError('Foo.prototype.method 只能在Foo的实例上调用!');
		}
	}
}

上面的代码保证了Foo的实例方法,只能在Foo的实例上调用。这里使用WeakSet的好处是,foos对实例的引用,不会被计入内存回收机制,所以删除实例的时候,不用考虑foos,也不会出现内存泄漏。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值