mozilla

Revision 336513 of WeakMap

  • Revision slug: JavaScript/Reference/Global_Objects/WeakMap
  • Revision title: WeakMap
  • Revision id: 336513
  • Created:
  • Creator: saneyuki_s
  • Is current revision? No
  • Comment

Revision Content

{{ Harmony() }}

Introduction

WeakMaps are key/value maps in which keys are objects.

API

Method Description
myWeakMap.get(key [, defaultValue]) Returns the value associated to the key object, defaultValue if there is none.
myWeakMap.set(key, value) Set the value for the key object in myWeakMap. Returns undefined.
myWeakMap.has(key) Returns a boolean asserting whether a value has been associated to the key object in myWeakMap or not
myWeakMap.delete(key) Removes any value associated to the key object. After such a call, myWeakMap.has(key) will return false.
myWeakMap.clear() Empty the myWeakMap from all its elements. Returns undefined.

Example

var wm1 = new WeakMap(),
    wm2 = new WeakMap(),
    wm3 = 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')

wm3.set(o1, 37);
wm3.get(o1); // 37
wm3.clear();
wm3.get(o1); // undefined, because wm3 was cleared and there is no value for o1 anymore

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

Why WeakMap?

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.

Because of references being weak, WeakMap keys are not enumerable (i.e. there is no method giving you a list of the keys). If they were, the list would depend on the state of garbage collection, introducing non-determinism. If you want to have a list of keys, you should maintain it yourself. There is also an ECMAScript proposal aiming at introducing simple sets and maps which would not use weak references and would be enumerable.

Specifications

Specification Status Comment
{{SpecName('Harmony')}} {{Spec2('Harmony')}}  

Browser compatibility

{{CompatibilityTable}}

Feature Chrome Firefox (SpiderMonkey) Internet Explorer Opera Safari
Basic support {{CompatVersionUnknown}}[1] {{CompatGeckoDesktop("6.0")}} {{CompatNo}} {{CompatNo}} {{CompatNo}}
clear() {{CompatNo}} {{CompatGeckoDesktop("20.0")}} {{CompatNo}} {{CompatNo}} {{CompatNO}}
Feature Android Firefox Mobile (SpiderMonkey) IE Mobile Opera Mobile Safari Mobile
Basic support {{CompatNo}} {{CompatGeckoMobile("6.0")}} {{CompatNo}} {{CompatNo}} {{CompatNo}}
clear() {{CompatNo}} {{CompatGeckoMobile("20.0")}} {{CompatNo}} {{CompatNo}} {{CompatNo}}

[1] The feature is available behind a pref. Go to chrome://flags and activate the entry “Enable Experimental JavaScript”.

See also

Revision Source

<p>{{ Harmony() }}</p>
<h2 id="Introduction">Introduction</h2>
<p>WeakMaps are key/value maps in which keys are objects.</p>
<h2 id="API">API</h2>
<table class="standard-table">
  <tbody>
    <tr>
      <th>Method</th>
      <th>Description</th>
    </tr>
    <tr>
      <td><code>myWeakMap.get(key&nbsp;[,&nbsp;defaultValue])</code></td>
      <td>Returns the value associated to the <code>key</code> object, <code>defaultValue</code> if there is none.</td>
    </tr>
    <tr>
      <td><code>myWeakMap.set(key,&nbsp;value)</code></td>
      <td>Set the value for the <code>key</code> object in <code>myWeakMap</code>. Returns <code>undefined</code>.</td>
    </tr>
    <tr>
      <td><code>myWeakMap.has(key)</code></td>
      <td>Returns a boolean asserting whether a value has been associated to the <code>key</code> object in <code>myWeakMap</code> or not</td>
    </tr>
    <tr>
      <td><code>myWeakMap.delete(key)</code></td>
      <td>Removes any value associated to the <code>key</code> object. After such a call, <code>myWeakMap.has(key)</code> will return <code>false</code>.</td>
    </tr>
    <tr>
      <td><code>myWeakMap.clear()</code></td>
      <td>Empty the <code>myWeakMap</code> from all its elements. Returns <code>undefined</code>.</td>
    </tr>
  </tbody>
</table>
<h2 id="Example">Example</h2>
<pre class="brush: js">
var wm1 = new WeakMap(),
    wm2 = new WeakMap(),
    wm3 = 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')

wm3.set(o1, 37);
wm3.get(o1); // 37
wm3.clear();
wm3.get(o1); // undefined, because wm3 was cleared and there is no value for o1 anymore

wm1.has(o1);   // true
wm1.delete(o1);
wm1.has(o1);   // false
</pre>
<h2 id="Why_WeakMap.3F">Why <em>Weak</em>Map?</h2>
<p>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.</p>
<p>Because of references being weak, WeakMap keys are not enumerable (i.e. there is no method giving you a list of the keys). If they were, the list would depend on the state of garbage collection, introducing non-determinism. If you want to have a list of keys, you should maintain it yourself. There is also an <a class="external" href="http://wiki.ecmascript.org/doku.php?id=harmony:simple_maps_and_sets">ECMAScript proposal</a> aiming at introducing simple sets and maps which would not use weak references and would be enumerable.</p>
<h2 id="Specifications" name="Specifications">Specifications</h2>
<table class="standard-table">
  <thead>
    <tr>
      <th scope="col">Specification</th>
      <th scope="col">Status</th>
      <th scope="col">Comment</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>{{SpecName('Harmony')}}</td>
      <td>{{Spec2('Harmony')}}</td>
      <td>&nbsp;</td>
    </tr>
  </tbody>
</table>
<h2 id="Browser_compatibility">Browser compatibility</h2>
<p>{{CompatibilityTable}}</p>
<div id="compat-desktop">
  <table class="compat-table">
    <tbody>
      <tr>
        <th>Feature</th>
        <th>Chrome</th>
        <th>Firefox (SpiderMonkey)</th>
        <th>Internet Explorer</th>
        <th>Opera</th>
        <th>Safari</th>
      </tr>
      <tr>
        <td>Basic support</td>
        <td>{{CompatVersionUnknown}}[1]</td>
        <td>{{CompatGeckoDesktop("6.0")}}</td>
        <td>{{CompatNo}}</td>
        <td>{{CompatNo}}</td>
        <td>{{CompatNo}}</td>
      </tr>
      <tr>
        <td><code>clear()</code></td>
        <td>{{CompatNo}}</td>
        <td>{{CompatGeckoDesktop("20.0")}}</td>
        <td>{{CompatNo}}</td>
        <td>{{CompatNo}}</td>
        <td>{{CompatNO}}</td>
      </tr>
    </tbody>
  </table>
</div>
<div id="compat-mobile">
  <table class="compat-table">
    <tbody>
      <tr>
        <th>Feature</th>
        <th>Android</th>
        <th>Firefox Mobile (SpiderMonkey)</th>
        <th>IE Mobile</th>
        <th>Opera Mobile</th>
        <th>Safari Mobile</th>
      </tr>
      <tr>
        <td>Basic support</td>
        <td>{{CompatNo}}</td>
        <td>{{CompatGeckoMobile("6.0")}}</td>
        <td>{{CompatNo}}</td>
        <td>{{CompatNo}}</td>
        <td>{{CompatNo}}</td>
      </tr>
      <tr>
        <td><code>clear()</code></td>
        <td>{{CompatNo}}</td>
        <td>{{CompatGeckoMobile("20.0")}}</td>
        <td>{{CompatNo}}</td>
        <td>{{CompatNo}}</td>
        <td>{{CompatNo}}</td>
      </tr>
    </tbody>
  </table>
</div>
<p>[1] The feature is available behind a pref. Go to <code>chrome://flags</code> and activate the entry “Enable Experimental JavaScript”.</p>
<h2 id="See_also">See also</h2>
<ul>
  <li><a class="link-https" href="https://bugzilla.mozilla.org/show_bug.cgi?id=547941">WeakMap bug at Mozilla</a></li>
</ul>
Revert to this revision