17

After reading this description: http://wiki.ecmascript.org/doku.php?id=harmony:weak_maps

I'm trying to get a hang of it, but I do not get the overall picture. What is it all about? It seems to be supported in Firefox 6: http://kangax.github.com/es5-compat-table/non-standard/

Paul Sweatte
  • 22,871
  • 7
  • 116
  • 244
Tower
  • 87,855
  • 117
  • 329
  • 496
  • The answers here are all wrong. The only thing "Weak" in a weak map is the keys. That is - if you have a key-value in a weak map than unlike a regular `Map` it will not prevent it from being garbage collected. This is useful for example for extending objects from the outside without messing with garbage collection. In particular the answer by Raynos just explains what a Map is. – Benjamin Gruenbaum Feb 27 '15 at 02:11
  • 2
    Related: [What are the actual uses of ES6 WeakMap?](http://stackoverflow.com/q/29413222/1114) – Jeremy Apr 23 '15 at 04:38
  • **Warning: Both answers here are incorrect**. See the post linked to in the comment above this one for meaningful answers. – Benjamin Gruenbaum Apr 24 '15 at 09:22

3 Answers3

15

A weak reference is a special object containing an object-pointer, but does not keep that object alive.

One application of weak references are implemented in Weak Maps:

“The experienced JavaScript programmer will notice that this API could be implemented in JavaScript with two arrays (one for keys, one for values) shared by the 4 API methods. Such an implementation would have two main inconveniences. The first one is an O(n) search (n being the number of keys in the map). The second one is a memory leak issue. With manually written maps, the array of keys would keep references to key objects, preventing them from being garbage collected. In native WeakMaps, references to key objects are held “weakly”, which means that they do not prevent garbage collection in case there would be no other reference to the object.” Source

(See also my post when ECMAScript Harmony was first released with Firefox... )

Lorenz Lo Sauer
  • 20,692
  • 12
  • 75
  • 85
11

WeakMap

WeakMaps basically allow you to have a HashTable with a key that isn't a String.

So you can set the key to be, i.e. [1] and then can say Map.get([1])

Example from the MDN:

var wm1 = new WeakMap(),
    wm2 = new WeakMap();
var o1 = {},
    o2 = function(){},
    o3 = window;

wm1.set(o1, 37);
wm1.set(o2, "azerty");
wm2.set(o1, o2); // a value can be anything, including an object or a function
wm2.set(o3, undefined);
wm2.set(wm1, wm2); // keys and values can be any objects. Even WeakMaps!

wm1.get(o2); // "azerty"
wm2.get(o2); // undefined, because there is no value for o2 on wm2
wm2.get(o3); // undefined, because that is the set value

wm1.has(o2); // true
wm2.has(o2); // false
wm2.has(o3); // true (even if the value itself is 'undefined')

wm1.has(o1);   // true
wm1.delete(o1);
wm1.has(o1);   // false

The reason for its existance is:

in order to fix a memory leak present in many uses of weak-key tables.

Apparently emulating weakmaps causes memory leaks. I don't know the details of those memory leaks.

alex
  • 438,662
  • 188
  • 837
  • 957
Raynos
  • 156,883
  • 55
  • 337
  • 385
  • 5
    The reason for the memory leak is that to implement it yourself, you need to store the keys in an array, which means they will never be garbage collected, even if every other reference is gone so there's no possible way to access the corresponding value anyway. – Matthew Crumley Oct 11 '11 at 20:59
0

WeakMap allows to use objects as keys. It does not have any method to know the length of the map. The length is always 1. The key can't be primitive values

A word of caution about using object as key is, since all the objects are by default singletons in JavaScript we should be creating an object reference and use it.

This is because when we create anonymous objects they are different.

if ( {} !== {} ) { console.log('Objects are singletons') };
// will print "Objects are singletons" 

So in the following scenario, we can't expect to get the value

var wm = new WeakMap()
wm.set([1],'testVal');
wm.get([1]);  // will be undefined

And the following snippet will work as expected.

var a = [1];
wm.set(a, 'testVal');
wm.get(a); // will return 'testVal'   
sreekarun
  • 167
  • 3