Categories
Modern JavaScript

Best of Modern JavaScript — Maps and WeakMaps

Spread the love

Since 2015, JavaScript has improved immensely.

It’s much more pleasant to use it now than ever.

In this article, we’ll look at maps and weak maps.

Iterating and Looping Through Maps

We can iterate and loop through maps with various methods.

Map.prototype.entries returns an iterable object with arrays of key-value pair arrays for each entry of our map.

Map.prototype.forEach takes a callback that has the signature (value, key, collection) to let us loop through the map.

value has the value of the map entry.

key has the key of the map entry.

collection has the map itself.

The 2nd argument of it is the value of this inside the callback.

Map.prototype.keys returns an iterable with the keys of the map.

Map.prototype.values returns an iterable of all values in the map.

Map.prototype[Symbol.iterator] is the default method for iterating through maps.

It returns an iterable with the key-value pair arrays.

WeakMap

WeakMaps work mostly like maps.

WeakMaps keys are objects. They’re weakly held.

We can’t get an overview of all the entries with a WeakMap.

And we can’t clear a WeakMap.

We’ve to put in objects as keys, so we can’t write;

const wm = new WeakMap()

wm.set('foo', 123);

since we’ll get a TypeError doing so.

But we can write:

const wm = new WeakMap()

wm.set({}, 123);

The WeakMap keys are weakly held.

This means that an object that isn’t referred to by anything like an object or a property can be garbage collected.

We can’t access them unless they’re held somewhere.

Once the key is gone, then the entry will disappear.

We can’t get an overview of a WeakMap.

This is because there’s no way to inspect the innards of it.

The only way to get the content of a WeakMap is to get the content by the key.

The use case of a WeakMap includes things like caching, managing listeners, and keeping private data.

With WeakMaps, we can cache an object with it, as we can only have object keys.

For example, we can write:

const cache = new WeakMap();

function countOwnKeys(obj) {
  if (cache.has(obj)) {
    return cache.get(obj);
  } else {
    const num = Math.random();
    cache.set(obj, num);
    return num;
  }
}

to create a WeakMap and get the entry if the key exists

Otherwise, we add an entry to the WeakMap.

We can also use them to store the listeners in a WeakMap.

For instance, we can write:

const listeners = new WeakMap();

function addListener(obj, listener) {
  if (!listeners.has(obj)) {
    listeners.set(obj, new Set());
  }
  listeners.get(obj).add(listener);
}

We have the addListener function to add an event listener to the set if it doesn’t already exist.

If obj isn’t in the WeakMap, then we create an entry the obj as the key and a set as the value.

It’s also useful for keeping private data as we need the reference to the key object to get the entry.

So we can write:

const _counter = new WeakMap();

class Countdown {
  constructor(counter) {
    _counter.set(this, counter);
  }

  increment() {
    let counter = _counter.get(this);
    if (counter < 1) {
      return;
    }
    counter++;
    _counter.set(this, counter);
  }
}

to store the counter in the WeakMap with the set method call in the constructor.

In the increment method, we get the counter with the _counter.get method.

Then we increment the counter and set the new value with set .

Conclusion

We can iterate through maps with various methods.

Also, WeakMaps can be used to store private data, caching, and more.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *