51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

JS中的WeakMap与WeakSet

介绍 {#介绍}

WeakMapWeakSet都是一种优化使用内存的解决方案。这两个数据结构的引用不会导致这些对象不被回收。上来就说这些有点太枯燥了,还是先聊聊它们能干什么。

WeakSet {#WeakSet}

集合就是一堆互异的数据,想必这个读者都早就明白了,这里不多说。

相对于正统SetWeakSet只提供三个方法:adddeletehas。正如前文所说,它们的引用GC是不管的,所以它也不清楚自己到底引用了多少个对象,故只能判断这个对象存在与否,和增删对象。

说了这么多,还是来点代码:

|-------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 | const set = new WeakSet() let mike = { name: 'Mike', age: 17 } let john = { name: 'John', age: 18 } set.add(john).add(mike) john = undefined |

当运行完这段代码的时候,john已经不再引用原来的对象,此时存放于set中的原john对象就可以被删掉了。但是到底删不删还是由JS引擎说得算的。

既然它对于对象都是弱引用,那么它就不能添加一个不是对象的基本类型。

|-------------|-----------------------------------------------------------------| | 1 2 | set.add(1) // TypeError: Invalid value used in weak set |

WeakMap {#WeakMap}

上文提到的WeakSet,我是不知道它到底被广泛应用到哪里了。但是WeakMap有一个特别有用的地方:存储私有变量。

我们知道,JS中没有真正的私有,但是我在使用TS编译器就运用了WeakMap来储存所谓的私有变量。这里演示一下其原理,因为TS编译后的代码不是人看的:

|------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | const barStorage = new WeakMap() class Foo { constructor(bar) { barStorage.set(this, bar) } get bar() { return barStorage.get(this) } set bar(_) { throw new Error('cannot set private member!') } } const foo1 = new Foo(2) const foo2 = new Foo(3) console.log(foo1.bar, foo2.bar) // 2 3 foo1.bar = 21 // Error: cannot set private member! |

由于WeakMap对对象的引用不会被GC当回事,所以当我们foo1foo2使用完毕被回收后,它们在WeakMap里的引用也会被清除掉,这样就节约了内存。

顺带一提,同WeakSet一样,WeakMap的键必须是对象:

|-------------|-------------------------------------------------------------------------------| | 1 2 | barStorage.set(1, 2) // TypeError: Invalid value used as weak map key |

这样就保证了当作为键的对象被回收后,它存的值也会被回收。

赞(1)
未经允许不得转载:工具盒子 » JS中的WeakMap与WeakSet