共计 3347 个字符,预计需要花费 9 分钟才能阅读完成。
点击在线浏览,体验更好 | 链接 |
---|---|
古代 JavaScript 高级小册 | 链接 |
深入浅出 Dart | 链接 |
古代 TypeScript 高级小册 | 链接 |
深刻了解 JavaScript 中的 WeakMap 和 WeakSet
在 JavaScript 的 ES6 版本中,引入了两种新的数据结构——WeakMap
和 WeakSet
。与 Map 和 Set 相比,这两种数据结构有一些非凡的特点和用处,因而在某些场合下,它们是更好的抉择。本文将深入探讨WeakMap
和WeakSet
的个性和用处。
1. WeakMap 和 WeakSet 概述
在咱们深入研究这两种新的数据结构之前,首先来理解一下它们的根本个性。
1.1 WeakMap
WeakMap
是一种键值对的汇合,相似于 Map
。不过,WeakMap
与Map
有几个重要的区别:
- 在
WeakMap
中,只有对象能够作为键。换句话说,咱们不能应用根本类型(如数字,字符串,布尔值等)作为WeakMap
的键。 WeakMap
的键是弱援用的。这意味着,如果一个对象只被WeakMap
援用,那么这个对象能够被垃圾回收(GC)。当这个对象被垃圾回收后,它对应的键值对也会从WeakMap
中主动移除。WeakMap
不可遍历,也就是说,咱们不能应用像for...of
这样的循环来遍历WeakMap
。
因为这些个性,WeakMap
在解决内存透露问题和治理对象公有数据等场景中有着显著的劣势。
1.2 WeakSet
WeakSet
也是一种汇合,相似于 Set
。WeakSet
与Set
的次要区别包含:
- 在
WeakSet
中,只有对象能够作为值。也就是说,咱们不能将根本类型(如数字,字符串,布尔值等)增加到WeakSet
中。 WeakSet
中的对象是弱援用的。如果一个对象只被WeakSet
援用,那么这个对象能够被垃圾回收。当这个对象被垃圾回收后,它会主动从WeakSet
中移除。WeakSet
不可遍历,也就是说,咱们不能应用像for...of
这样的循环来遍历WeakSet
。
WeakSet
在解决对象的唯一性、内存透露等问题上有其独特的利用。
2. WeakMap 深刻解析
上面,咱们将更深刻地探讨 WeakMap
的个性和用法。
2.1 WeakMap 的创立和应用
咱们能够应用 new WeakMap()
来创立一个新的 WeakMap
。在创立了WeakMap
之后,咱们能够应用 set
办法来增加新的键值对,
应用 get
办法来获取某个键对应的值,应用 delete
办法来移除某个键及其对应的值,应用 has
办法来查看 WeakMap
中是否存在某个键。
let weakMap = new WeakMap();
let obj1 = {};
let obj2 = {};
// 增加键值对
weakMap.set(obj1, 'Hello');
weakMap.set(obj2, 'World');
// 获取值
console.log(weakMap.get(obj1)); // 输入: 'Hello'
console.log(weakMap.get(obj2)); // 输入: 'World'
// 查看键是否存在
console.log(weakMap.has(obj1)); // 输入: true
console.log(weakMap.has(obj2)); // 输入: true
// 删除键值对
weakMap.delete(obj1);
console.log(weakMap.has(obj1)); // 输入: false
2.2 WeakMap 和内存治理
WeakMap
最重要的个性就是其键对对象的弱援用。这意味着,如果一个对象只被 WeakMap
援用,那么这个对象能够被垃圾回收。这样就能够避免因为长时间持有对象援用导致的内存透露。
例如,如果咱们在 Map
中保留了一些对象的援用,即便这些对象在其余中央都曾经不再应用,然而因为它们仍被 Map
援用,所以它们不能被垃圾回收,这就可能导致内存透露。然而,如果咱们应用 WeakMap
来保留这些对象的援用,那么当这些对象在其余中央都不再应用时,它们就会被垃圾回收,从而避免了内存透露。
2.3 WeakMap 和对象公有数据
WeakMap
还经常被用来保留对象的公有数据。这是因为 WeakMap
的键不可遍历,所以咱们能够利用这个个性来存储一些只有特定代码可能拜访的数据。
例如,咱们能够创立一个 WeakMap
,而后应用这个WeakMap
来保留每个对象的公有数据,像这样:
let privateData = new WeakMap();
function MyClass() {
privateData.set(this, {secret: 'my secret data',});
}
MyClass.prototype.getSecret = function() {return privateData.get(this).secret;
};
let obj = new MyClass();
console.log(obj.getSecret()); // 输入: 'my secret data'
在这个例子中,咱们创立了一个 MyClass
的类,每一个 MyClass
的实例都有一个公有数据 secret
。咱们应用WeakMap
来保留这个公有数据。这样,咱们就能够在 MyClass
的办法中拜访这个公有数据,然而其余的代码无法访问它。
3. WeakSet 深刻解析
接下来,咱们将更深刻地探讨 WeakSet
的个性和用法。
3.1 WeakSet 的创立和应用
咱们能够应用 new WeakSet()
来创立一个新的 WeakSet
。在创立了WeakSet
之后,咱们能够应用 add
办法来增加新的对象,应用 delete
办法来移除某个对象,应用 has
办法来查看 WeakSet
中是否存在某个对象。
let weakSet = new WeakSet();
let obj1 = {};
let obj2 = {};
// 增加对象
weakSet.add(obj1);
weakSet.add(obj2);
// 查看对象是否存在
console.log(weakSet.has(obj1)); // 输入: true
console.log(weakSet.has(obj2)); // 输入: true
// 删除对象
weakSet.delete(obj1);
console.log(weakSet.has(obj1)); // 输入: false
3.2 WeakSet 和对象唯一性
WeakSet
能够用来查看一个对象是否曾经存在。因为 WeakSet
中的每个对象都是惟一的,所以咱们能够利用这个个性来确保咱们不会增加反复的对象。
例如,咱们能够创立一个 WeakSet
,而后应用这个WeakSet
来保留所有咱们曾经解决过的对象,像这样:
let processedObjects = new WeakSet();
function processObject(obj) {if (!processedObjects.has(obj)) {
// 解决对象
// ...
// 将对象增加到 WeakSet 中,示意咱们曾经解决过这个对象
processedObjects.add(obj);
}
}
在这个例子中,咱们在每次解决一个对象之前,都会查看这个对象是否曾经被解决过。如果这个对象曾经被解决过,咱们就不会再解决它。这样,咱们就能够确保咱们不会反复解决同一个对象。
3.3 WeakSet 和内存治理
与 WeakMap
一样,WeakSet
中的对象也是弱援用的,所以 WeakSet
也有优良的内存治理个性。如果一个对象只被 WeakSet
援用,那么这个对象能够被垃圾回收。这样就能够避免因为长时间持有对象援用导致的内存透露。
例如,如果咱们在 Set
中保留了一些对象的援用,即便这些对象在其余中央都曾经不再应用,然而因为它们仍被 Set
援用,所以它们不能被垃圾回收,这就可能导致内存透露。然而,如果咱们应用 WeakSet
来保留这些对象的援用,那么当这些对象在其余中央都不再应用时,它们就会被垃圾回收,从而避免了内存透露。
4. 论断
在 JavaScript 的 ES6 版本中,引入了 WeakMap
和WeakSet
这两种新的数据结构。与 Map
和Set
相比,它们有一些非凡的特点和用处,使它们在解决内存透露问题、治理对象公有数据、解决对象的唯一性等场景中有显著的劣势。了解它们的个性和用法,能够帮忙咱们更无效地应用 JavaScript 来编写高效、稳固的代码。