关于前端:现代JavaScript高级教程深入理解JavaScript中的WeakMap和WeakSet

46次阅读

共计 3347 个字符,预计需要花费 9 分钟才能阅读完成。

点击在线浏览,体验更好 链接
古代 JavaScript 高级小册 链接
深入浅出 Dart 链接
古代 TypeScript 高级小册 链接

深刻了解 JavaScript 中的 WeakMap 和 WeakSet

在 JavaScript 的 ES6 版本中,引入了两种新的数据结构——WeakMapWeakSet。与 Map 和 Set 相比,这两种数据结构有一些非凡的特点和用处,因而在某些场合下,它们是更好的抉择。本文将深入探讨WeakMapWeakSet的个性和用处。

1. WeakMap 和 WeakSet 概述

在咱们深入研究这两种新的数据结构之前,首先来理解一下它们的根本个性。

1.1 WeakMap

WeakMap是一种键值对的汇合,相似于 Map。不过,WeakMapMap有几个重要的区别:

  • WeakMap 中,只有对象能够作为键。换句话说,咱们不能应用根本类型(如数字,字符串,布尔值等)作为 WeakMap 的键。
  • WeakMap的键是弱援用的。这意味着,如果一个对象只被 WeakMap 援用,那么这个对象能够被垃圾回收(GC)。当这个对象被垃圾回收后,它对应的键值对也会从 WeakMap 中主动移除。
  • WeakMap不可遍历,也就是说,咱们不能应用像 for...of 这样的循环来遍历WeakMap

因为这些个性,WeakMap在解决内存透露问题和治理对象公有数据等场景中有着显著的劣势。

1.2 WeakSet

WeakSet也是一种汇合,相似于 SetWeakSetSet的次要区别包含:

  • 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 版本中,引入了 WeakMapWeakSet这两种新的数据结构。与 MapSet相比,它们有一些非凡的特点和用处,使它们在解决内存透露问题、治理对象公有数据、解决对象的唯一性等场景中有显著的劣势。了解它们的个性和用法,能够帮忙咱们更无效地应用 JavaScript 来编写高效、稳固的代码。

正文完
 0