DEV Community

Luiz Guilherme Pereira
Luiz Guilherme Pereira

Posted on

WeakMap in Javascript

Recently I've been abusing WeakMap to solve performance issues in Javascript.
The WeakMap work in a very similar way to its stronger brother Map. You provide a key and a value. Whenever you need to retrieve the value for that key, you can get it from the WeakMap.
The difference between Map and WeakMap is that the latter does not hold reference to the key, if the garbage collector needs to clear it from the memory, WeakMap will say that it is fine, the key and value will be cleared at the same time.

Caching

The power this characteristic gives us is that we can start caching things without the risk of causing a memory leak. If the key is ready to be collected, the cache won't be a problem in the way of GC.

We can implement a higher-order function called weakMemoize that will decorate our function with a caching layer using a WeakMap.

function weakMemoize(toDecorate) {
  const cache = new WeakMap()
  return function (value) {
    if (!cache.has(value)) {
      cache.set(value, toDecorate(value))
    }
    return cache.get(value)
  }
}
Enter fullscreen mode Exit fullscreen mode

Then we can use to cache our functions

const getKeys = weakMemoize((value) => {
    return Object.keys(value)
})

const obj = { a: 10, b: 20, c: 30 }

getKeys(obj)
// second time the value is read from the cache.
getKeys(obj)
Enter fullscreen mode Exit fullscreen mode

I'm not concerned about the memory consumption of this because whenever obj or getKeys go out of scope, the garbage collector will also collect the values in the map. I'm avoiding executing Object.keys a second time with no extra complexity in the implementation of my function.

Considerations

Couple of things to take in consideration. A WeakMap key can only be an object (object or Array), we cannot use a primitive value as key.
Another consideration is that if you have long living objects, caching things like this, might not be so beneficial, a lot of objects will be retained in memory, consider using a LRU cache.

Also, you don't need to implement your own weakMemoize, there are good implementations in the npm.

Thanks for reading!
Saw a problem in my post? Please comment or reach me out on twitter.

Top comments (0)