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

点击在线浏览,体验更好 链接
古代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来编写高效、稳固的代码。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理