集合引用类型
一、Map
-
内存占用: 给定固定大小的内存,Map可以比Object多存储50%的键值对; -
插入性能: 若插入键值对数量不多,则消耗大致相对;但是当涉及到大量插入操作,Map的性能更佳; -
查找速度 -
删除性能: Map的delete()操作性能更佳
二、WeakMap
- 概念: 称为弱映射,它是Map的兄弟类型,不同的是,weakMap的键只能是 Object 或者继承自 Object 的类型,尝试使用非对象设置键会抛出TypeError。值的类型没有限制; WeakMap 中的“weak”(弱),描述的是 JavaScript 垃圾回收程序对待“弱映射”中键的方式;
- 基本API
- 弱键:WeakMap 中“weak”表示弱映射的键是“弱弱地拿着”的。意思就是,这些键不属于正式的引用,不会阻止垃圾回收。但要注意的是,弱映射中值的引用可不是“弱弱地拿着”的。只要键存在,键/值对就会存在于映射中,并被当作对值的引用,因此就不会被当作垃圾回收。
eg1: set()方法初始化了一个新对象并将它用作一个字符串的键。因为没有指向这个对象的其他引用,所以当这行代码执行完成后,这个对象键就会被当作垃圾回收。然后,这个键/值对就从弱映射中消失了,使其成为一个空映射。在这个例子中,因为值也没有被引用,所以这对键/值被破坏以后,值本身也会成为垃圾回收的目标
eg2: 因为container 对象维护着一个对弱映射键的引用,因此这个对象键不会成为垃圾回收的目标。不过,如果调用了 removeReference(),就会摧毁键对象的最后一个引用,垃圾回收程序就可以把这个键/值对清理掉。
- 不可迭代,因为WeakMap 中的键/值对任何时候都可能被销毁
- 不能clear()
- 作为私有变量:弱映射造就了在 JavaScript 中实现真正私有变量的一种新方式。前提很明确:私有变量会存储在弱映射中,以对象实例为键,以私有成员的字典为值。
const User = (() => {
const wm = new WeakMap();
class User {
constructor(id) {
this.idProperty = Symbol('id');
this.setId(id);
}
setPrivate(property, value) {
const privateMembers = wm.get(this) || {};
privateMembers[property] = value;
wm.set(this, privateMembers);
}
getPrivate(property) {
return wm.get(this)[property];
}
setId(id) {
this.setPrivate(this.idProperty, id);
}
getId(id) {
return this.getPrivate(this.idProperty);
}
}
return User;
})();
const user = new User(123);
console.log(user.getId());
user.setId(456);
console.log(user.getId());
- 保存DOM节点元数据
三、 Set
- 基本使用、迭代方法与Map类似
- 基本API
- 定义一个正式集合:可以在子类上实现静态方法,然后在实例方法中使用这些静态方法。
class XSet extends Set {
union(...sets) {
return XSet.union(this, ...sets)
}
intersection(...sets) {
return XSet.intersection(this, ...sets);
}
difference(set) {
return XSet.difference(this, set);
}
symmetricDifference(set) {
return XSet.symmetricDifference(this, set);
}
cartesianProduct(set) {
return XSet.cartesianProduct(this, set);
}
powerSet() {
return XSet.powerSet(this);
}
static union(a, ...bSets) {
const unionSet = new XSet(a);
for (const b of bSets) {
for (const bValue of b) {
unionSet.add(bValue);
}
}
return unionSet;
}
static intersection(a, ...bSets) {
const intersectionSet = new XSet(a);
for (const aValue of intersectionSet) {
for (const b of bSets) {
if (!b.has(aValue)) {
intersectionSet.delete(aValue);
}
}
}
return intersectionSet;
}
static difference(a, b) {
const differenceSet = new XSet(a);
for (const bValue of b) {
if (a.has(bValue)) {
differenceSet.delete(bValue);
}
}
return differenceSet;
}
static symmetricDifference(a, b) {
return a.union(b).difference(a.intersection(b));
}
static cartesianProduct(a, b) {
const cartesianProductSet = new XSet();
for (const aValue of a) {
for (const bValue of b) {
cartesianProductSet.add([aValue, bValue]);
}
}
return cartesianProductSet;
}
static powerSet(a) {
const powerSet = new XSet().add(new XSet());
for (const aValue of a) {
for (const set of new XSet(powerSet)) {
powerSet.add(new XSet(set).add(aValue));
}
}
return powerSet;
}
}
四、WeakSet
- 弱集合中的值只能是 Object 或者继承自 Object 的类型,尝试使用非对象设置值会抛出 TypeError。
- 同样具有不可迭代性、不会阻止垃圾回收的特性
- 使用场景
|