Web App Development

Difference between Map and WeakMap in JavaScript

ES2015 introduced the new Map and WeakMap objects to JavaScript. They can be used as a key-value store, but unlike normal objects in JavaScript you can use objects as keys. Keys for normal objects ({}) always have to be strings, and if you try to use an object it will be converted to a string ([object Object]).

Using Maps

To assign values to a map you need to use the set method:

window.obj = {}
var map = new Map()
map.set(window.obj, 123)

(You’ll see later why I’m assigning obj to window rather than using a local variable.)

Then, to retrieve the object call get:

map.get(window.obj) // => 123

Difference between Map and WeakMap

The difference between Map and WeakMap lies in how the objects that are used as keys are treated during garbage collection.

Without the Maps, running delete window.obj would remove the only reference to the obj object, and the object would be removed from memory.

However, since obj is used as a key in our Map there still is a reference to obj and it can’t be garbage collected.

WeakMaps however are different: they act as if there was no additional reference to obj. They only hold a weak reference to obj, meaning that after running removing the obj reference from the window object, obj can be garbage collected.

Let’s change our code a bit to make obj use up more memory:

function Obj(){
    this.val = new Array(10000000).join("---")
}

window.obj = new Obj();
var map = new Map()
map.set(window.obj, 123)
delete window.obj

If you run this in Chrome the memory consumption will rise by about 30MB. Here’s the screenshot from the DevTools memory profiler:

Heap snapshot with WeakMap

Now let’s try the same thing with a WeakMap:

function Obj(){
    this.val = new Array(10000000).join("---")
}

window.obj = new Obj();
var map = new WeakMap()
map.set(window.obj, 123)
delete window.obj

You can see from the heap snapshot that the memory used by obj has been garbage collected:

Heap snapshot with WeakMap

Browser support for Map and WeakMap

The latest Chrome, Firefox, Edge and Safari support Map and WeakMap on desktop. There’s no support in IE10.

On mobile newer browsers also have support, but IE Mobile doesn’t.

A gotcha when trying this in the console

When I was playing around in the DevTools console I ran into some trouble, because memory wasn’t cleared up when I expected it to be.

It turned out that the problem was that the large object had been printed in the console, which caused Chrome to keep the object in memory.

The solution was to prevent obj being logged in the console. In this case I’m just adding a meaningless 123; statement that appears in the console instead:


Follow me on Twitter