ES6中 Set和WeakSet数据结构
Set
Set是类似于数组,但是成员变量的值都是唯一的,没有重复的值
Set的方法和属性
属性
Set.prototype.size: 返回Set实例的成员数量。 Set.prototype.constructor: 默认的构造Set函数。
操作函数
add(value): 添加某个值,返回Set结构本身。 delete(value): 删除某个值,返回一个布尔值,表示删除成功。 has(value): 返回一个布尔值,表示参数是否为Set的成员。 clear(): 清除所有成员,没有返回值。
内部迭代器 keys() : 返回一个键名的遍历器 values()(默认迭代器) : 返回一个值的遍历器 entries() : 返回一个键值对的遍历器 forEach(): 使用回调函数遍历每个成员
for(let item of set.keys()){}
for(let item of set.values()){}
for(let item of set.entries()){}
注意: 由于Set没有键名,只有值名,keys()和values()返回的结果是一样,
forEach方法的回调函数接收3个参数:(键值,键名,集合本身)
另外,forEach方法还有第二个参数,表示绑定this的对象。
Set实现并集,交集,差集
let set1 = new Set([1,2,3,4,5,6]);
let set2 = new Set([4,5,6,7,8,9]);
并集
let union = new Set([...set1,...set2]); //[1,2,3,4,5,6,7,8,9]
交集
let intersect1 = new Set([...set1].filter(x => let2.has(x))); //[4,5,6]
差集
let intersect2 = new Set([...set1].filter(x => !let2.has(x))); //[1,2,3,4]
WeakSet
- WeakSet 成员只能够是对象
- 作为 WeakSet 成员的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在与WeakSet之中。这个特点意味着,无法引用WeakSet的成员,因此WeakSet是不可遍历的。
- 使用WeakSet存储对象实例的好处是,由于是对对象实例的引用,不会被计入内存回收机制,所以删除实例的时候,不用考虑weaket,也不会出现内存泄漏。
var ws = new WeakSet();
ws.add(1) //TypeError:Invalid value used in weak set
ws.add(Symbol) //TypeError:Invalid value used in weak set
添如一个数值和一个Symbol,结果同时报错。
WeakSet的方法 add(value): 向WeakSet实例添加一个新成员。 delete(value): 删除WeakSet实例指定成员。 has(value): 返回一个布尔值,表示某个值是否在WeakSet实例中。
弱引用,不被计入垃圾回收
添加进WeakSet的元素对象,WeakSet不会对元素对像的引用计数加1,对于被添加进WeakSet的元素对象,只要该元素对象没有被除WeakSet以外的其他对象引用,就会被垃圾回收释放,在WeakSet中的该元素对象自动被释放,不会出现内存泄漏。
因为这一特性,其性能要比map要高,对于存储无顺序要求的,不重复的,临时存储的场景,可以使用它。
const ws = new WeakSet()
var a = {p1:'1', p2:'2'}
ws.add(a)
a = null // 把对象删除,weakset中的对象也没了,垃圾回收机制,置空
console.log(ws.has(a)) // weakset不能取值,也不能显示,只用来表示是否有重复的对象
先将对象添加到WeakSet中,然后将对象设成null,然后再下面的has方法判定时,结果显示,表示WeakSet中已经不存在该对象。
下面是 WeakSet 的另一个例子。
const foos = new WeakSet()
class Foo {
constructor() {
foos.add(this)
}
method () {
if (!foos.has(this)) {
throw new TypeError('Foo.prototype.method 只能在Foo的实例上调用!');
}
}
}
上面代码保证了Foo的实例方法,只能在Foo的实例上调用。这里使用WeakSet的好处是,foos对实例的引用,不会被计入内存回收机制,所以删除实例的时候,不用考虑foos,也不会出现内存泄漏。
3.不能遍历
因为其对内部的元素对象是弱引用,随时会被垃圾回收释放掉,所以其不支持size和forEach等遍历方法。
WeakSet的一个用处是存储DOM节点,而不用担心这些节点从文档移除时,会引起内存的泄露。