JavaScript Map, Set, WeakMap and WeakSet.
Published: 2023-06-07 17:10:01

## JavaScript Map and Set

### Map

A `Map` object is a collection of key-value pairs where each key can be of any type. This means that you can use objects, strings, numbers, or even functions as keys. A `Map` is similar to an object, but it provides additional functionality, such as built-in methods for adding, deleting, and updating key-value pairs.

Here's an example of how you can create a `Map` object:

```javascript
const myMap = new Map();
```

You can then add key-value pairs to the map using the `set` method:

```javascript
myMap.set('key1', 'value1');
myMap.set('key2', 'value2');
myMap.set('key3', 'value2');//add same value
myMap.set("key2", "value3"); //add same key
```

You can retrieve the value associated with a key using the `get` method:

```javascript
console.log(myMap.get('key1')); // output: 'value1'
```

You can also delete a key-value pair using the `delete` method:

```javascript
myMap.delete('key1');
```

### Set

A `Set` object is a collectionof unique values where each value can be of any type. This means that you can use objects, strings, numbers, or even functions as values. A `Set` is useful when you want to store a collection of unique values and perform operations on them, such as finding the intersection or difference between two sets.

Here's an example of how you can create a `Set` object:

```javascript
const mySet = new Set();
```

You can then add values to the set using the `add` method:

```javascript
mySet.add('value1');
mySet.add('value2');
mySet.add("value2");// add same value
```

You can check if a value exists in the set using the `has` method:

```javascript
console.log(mySet.has('value1')); // output: true
```

You can also delete a value from the set using the `delete` method:

```javascript
mySet.delete('value1');
```

## JavaScript Garbage Collection

Garbage collection in JavaScript is the process of automatically freeing up memory that is no longer being used by your code. This is important because JavaScript is a dynamically typed language, which means that you can create and destroy objects at runtime.

JavaScript engines use a technique called "mark and sweep" to perform garbage collection. This involves marking all the objects that are still being used by your code and then sweeping up the objects that are not marked. This process is performed periodically by the JavaScript engine and is completely transparent to your code.

## Map vs WeakMap and when to use WeakMap

`Map` and `WeakMap` are both data structures in JavaScript, but they have some differences in terms of how they handle memory management.

A `Map` object holds strong references to its keys and values, which means that as long as the `Map` object exists, its keys and values will not be garbage collected. This can be useful in some cases, but it can also lead to memory leaks if you don't properly manage your `Map` objects.

On the other hand, a `WeakMap` object holds weak references to its keys. This means that if the only reference to a key is from the `WeakMap` object, the key will be automatically garbage collected. This can be useful in cases where you want to associate additional data with an object without keeping a strong reference to that object.

One common use case for `WeakMap` is in implementing private data for JavaScript objects. In JavaScript, there is no built-in support for private instance variables or methods, which can lead to issues with encapsulation and data hiding. However, `WeakMap` can be used to simulate private instance variables in JavaScript.

Here's an example:

```javascript
      const privateData = new WeakMap();

      class Counter {
        constructor() {
          privateData.set(this, { counter: 0 });
        }

        increment() {
          const data = privateData.get(this);
          data.counter++;
          console.log(`Counter is now ${data.counter}`);
        }
      }

      let counter1 = new Counter();
      counter1.increment();
      counter1.increment();
      counter1.increment();
      let counter2   = new Counter();
      counter2.increment();

```

In this example, we're using `WeakMap` to store private data for instances of `MyClass`. The `privateData` object is a `WeakMap` that maps instances of `MyClass` to an object containing the private data for that instance. The private data in this case is just a `counter` property that we're incrementing in the `incrementCounter` method.

Because `privateData` is a `WeakMap`, the private data for each instance of `MyClass` can be garbage collected when the instance itself is no longer reachable. This means that the private data is truly private to each instance of `MyClass`, and cannot be accessed from outside the class.

Another use case for `WeakMap` is in caching. For example, you could use a `WeakMap` to cache theresults of a time-consuming computation, where the keys are the arguments to the computation and the values are the results. Because `WeakMap` holds weak references to its keys, the cached results can be garbage collected when the arguments are no longer reachable, which can help to free up memory.

Here's an example:

```javascript
const cache = new WeakMap();

function computeResult(arg) {
  if (cache.has(arg)) {
    console.log('Using cached result');
    return cache.get(arg);
  }

  console.log('Computing result');
  const result = /* perform time-consuming computation */;
  cache.set(arg, result);
  return result;
}
```

In this example, we're using a `WeakMap` to cache the results of the `computeResult` function. The `cache` object is a `WeakMap` that maps arguments to results. When the function is called with a particular argument, we first check if the result is already cached. If it is, we return the cached result. If not, we perform the time-consuming computation to compute the result, and then cache the result in the `WeakMap`.

Because `cache` is a `WeakMap`, the cached results can be garbage collected when the arguments are no longer reachable, which can help to free up memory. This can be especially useful if the arguments are large objects or collections that take up a lot of memory.

## Conclusion

In summary, `Map` and `Set` are useful data structures in JavaScript for storing collections of key-value pairs and unique values, respectively. JavaScript garbage collection is the process of automatically freeing up memory that is no longer being used by your code. Finally, `Map` and `WeakMap` have some differences in terms of how they handle memory management, with `WeakMap` being useful in cases where you want to associate additional data with an object without keeping a strong reference to that object.