Please note, this is a STATIC archive of website developer.mozilla.org from 03 Nov 2016, cach3.com does not collect or store any user information, there is no "phishing" involved.

Revision 1068090 of WeakMap

  • Revision slug: Web/JavaScript/Reference/Global_Objects/WeakMap
  • Revision title: WeakMap
  • Revision id: 1068090
  • Created:
  • Creator: Havvy
  • Is current revision? No
  • Comment "Maintain it yourself" basically boils down to "Use a Map" because keeping the list keeps strong references right now. Should JS ever get weak refs for values, then being more generic would be more useful.

Revision Content

{{JSRef}}

The WeakMap object is a collection of key/value pairs in which the keys are weakly referenced.  The keys must be objects and the values can be arbitrary values.

Syntax

new WeakMap([iterable])

Parameters

iterable
Iterable is an Array or other iterable object whose elements are key-value pairs (2-element Arrays). Each key-value pair will be added to the new WeakMap. null is treated as undefined.

Description

Keys of WeakMaps are of the type Object only. {{Glossary("Primitive", "Primitive data types")}} as keys are not allowed (e.g. a {{jsxref("Symbol")}} can't be a WeakMap key).

The key in a WeakMap is held weakly.  What this means is that, if there are no other strong references to the key, then the entire entry will be removed from the WeakMap by the garbage collector.

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 four 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 use a {{jsxref("Map")}}.

Properties

WeakMap.length
The value of the length property is 0.
{{jsxref("WeakMap.prototype")}}
Represents the prototype for the WeakMap constructor. Allows the addition of properties to all WeakMap objects.

WeakMap instances

All WeakMap instances inherit from {{jsxref("WeakMap.prototype")}}.

Properties

{{page('en-US/Web/JavaScript/Reference/Global_Objects/WeakMap/prototype','Properties')}}

Methods

{{page('en-US/Web/JavaScript/Reference/Global_Objects/WeakMap/prototype','Methods')}}

Examples

Using WeakMap

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 key 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

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

Implementing a WeakMap-like class with a .clear() method

For expository purpose, the following example uses the new ECMAScript 6 class construct, which is currently not widely implemented.

class ClearableWeakMap {
  constructor(init) {
    this._wm = new WeakMap(init)
  }
  clear() {
    this._wm = new WeakMap()
  }
  delete(k) {
    return this._wm.delete(k)
  }
  get(k) {
    return this._wm.get(k)
  }
  has(k) {
    return this._wm.has(k)
  }
  set(k, v) {
    this._wm.set(k, v)
    return this
  }
}

Specifications

Specification Status Comment
{{SpecName('ES6', '#sec-weakmap-objects', 'WeakMap')}} {{Spec2('ES6')}} Initial definition.
{{SpecName('ESDraft', '#sec-weakmap-objects', 'WeakMap')}} {{Spec2('ESDraft')}}  

Browser compatibility

{{CompatibilityTable}}

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari
Basic support 36 {{CompatGeckoDesktop("6.0")}} 11 {{ CompatOpera(23) }} 7.1
new WeakMap(iterable) 38 {{CompatGeckoDesktop("36")}} {{CompatNo}} {{ CompatOpera(25) }} {{CompatNo}}
clear() 36 {{CompatNo}} [1] 11 {{ CompatOpera(23) }} 7.1
Constructor argument: new WeakMap(null) {{CompatVersionUnknown}} {{CompatGeckoDesktop("37")}} {{CompatUnknown}} {{CompatUnknown}} {{CompatUnknown}}
Monkey-patched set() in constructor {{CompatVersionUnknown}} {{CompatGeckoDesktop("37")}} {{CompatUnknown}} {{CompatUnknown}} {{CompatUnknown}}
WeakMap() without new throws {{CompatVersionUnknown}} {{CompatGeckoDesktop("42")}} {{CompatUnknown}} {{CompatUnknown}} {{CompatUnknown}}
Feature Chrome for Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Basic support 35 {{CompatGeckoMobile("6.0")}} {{CompatNo}} {{CompatNo}} 8
new WeakMap(iterable) 38 {{CompatGeckoMobile("36")}} {{CompatNo}} {{CompatNo}} {{CompatNo}}
clear() 35 {{CompatNo}} [1] {{CompatNo}} {{CompatNo}} 8
Constructor argument: new WeakMap(null) {{CompatUnknown}} {{CompatGeckoMobile("37")}} {{CompatNo}} {{CompatUnknown}} {{CompatUnknown}}
Monkey-patched set() in constructor {{CompatUnknown}} {{CompatGeckoMobile("37")}} {{CompatNo}} {{CompatUnknown}} {{CompatUnknown}}
WeakMap() without new throws {{CompatUnknown}} {{CompatGeckoMobile("42")}} {{CompatUnknown}} {{CompatUnknown}} {{CompatUnknown}}

[1] The clear() method has been supported from version 20 until version 45 (including).

See also

Revision Source

<div>{{JSRef}}</div>

<p>The <strong><code>WeakMap</code></strong> object is a collection of key/value pairs in which the keys are weakly referenced.&nbsp; The keys must be objects and the values can be arbitrary values.</p>

<h2 id="Syntax">Syntax</h2>

<pre class="syntaxbox">
new WeakMap([iterable])
</pre>

<h3 id="Parameters">Parameters</h3>

<dl>
 <dt><code>iterable</code></dt>
 <dd>Iterable is an Array or other iterable object whose elements are key-value pairs (2-element Arrays). Each key-value pair will be added to the new WeakMap. null is treated as undefined.</dd>
</dl>

<h2 id="Description">Description</h2>

<p>Keys of WeakMaps are of the type <code>Object</code> only. {{Glossary("Primitive", "Primitive data types")}} as keys are not allowed (e.g. a {{jsxref("Symbol")}} can't be a <code>WeakMap</code> key).</p>

<p>The key in a WeakMap is held weakly.&nbsp; What this means is that, if there are no other strong references to the key, then the entire entry will be removed from the WeakMap by the garbage collector.</p>

<h3 id="Why_WeakMap">Why <em>Weak</em>Map?</h3>

<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 four 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, <code>WeakMap</code> 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 use a {{jsxref("Map")}}.</p>

<h2 id="Properties">Properties</h2>

<dl>
 <dt><code>WeakMap.length</code></dt>
 <dd>The value of the <code>length</code> property is 0.</dd>
 <dt>{{jsxref("WeakMap.prototype")}}</dt>
 <dd>Represents the prototype for the <code>WeakMap</code> constructor. Allows the addition of properties to all <code>WeakMap</code> objects.</dd>
</dl>

<h2 id="WeakMap_instances"><code>WeakMap</code> instances</h2>

<p>All <code>WeakMap</code> instances inherit from {{jsxref("WeakMap.prototype")}}.</p>

<h3 id="Properties_2">Properties</h3>

<p>{{page('en-US/Web/JavaScript/Reference/Global_Objects/WeakMap/prototype','Properties')}}</p>

<h3 id="Methods">Methods</h3>

<p>{{page('en-US/Web/JavaScript/Reference/Global_Objects/WeakMap/prototype','Methods')}}</p>

<h2 id="Examples">Examples</h2>

<h3 id="Using_WeakMap">Using <code>WeakMap</code></h3>

<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 key 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

wm1.has(o1); // true
wm1.delete(o1);
wm1.has(o1); // false
</pre>

<h3 id="Implementing_a_WeakMap-like_class_with_a_.clear()_method">Implementing a <code>WeakMap</code>-like class with a .clear() method</h3>

<p>For expository purpose, the following example uses the new ECMAScript 6 <code>class</code> construct, which is currently not widely implemented.</p>

<pre class="brush: js">
class ClearableWeakMap {
  constructor(init) {
    this._wm = new WeakMap(init)
  }
  clear() {
    this._wm = new WeakMap()
  }
  delete(k) {
    return this._wm.delete(k)
  }
  get(k) {
    return this._wm.get(k)
  }
  has(k) {
    return this._wm.has(k)
  }
  set(k, v) {
    this._wm.set(k, v)
    return this
  }
}
</pre>

<h2 id="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('ES6', '#sec-weakmap-objects', 'WeakMap')}}</td>
   <td>{{Spec2('ES6')}}</td>
   <td>Initial definition.</td>
  </tr>
  <tr>
   <td>{{SpecName('ESDraft', '#sec-weakmap-objects', 'WeakMap')}}</td>
   <td>{{Spec2('ESDraft')}}</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 (Gecko)</th>
   <th>Internet Explorer</th>
   <th>Opera</th>
   <th>Safari</th>
  </tr>
  <tr>
   <td>Basic support</td>
   <td>36</td>
   <td>{{CompatGeckoDesktop("6.0")}}</td>
   <td>11</td>
   <td>{{ CompatOpera(23) }}</td>
   <td>7.1</td>
  </tr>
  <tr>
   <td><code>new WeakMap(iterable)</code></td>
   <td>38</td>
   <td>{{CompatGeckoDesktop("36")}}</td>
   <td>{{CompatNo}}</td>
   <td>{{ CompatOpera(25) }}</td>
   <td>{{CompatNo}}</td>
  </tr>
  <tr>
   <td><code>clear()</code></td>
   <td>36</td>
   <td>{{CompatNo}} [1]</td>
   <td>11</td>
   <td>{{ CompatOpera(23) }}</td>
   <td>7.1</td>
  </tr>
  <tr>
   <td>Constructor argument: <code>new WeakMap(null)</code></td>
   <td>{{CompatVersionUnknown}}</td>
   <td>{{CompatGeckoDesktop("37")}}</td>
   <td>{{CompatUnknown}}</td>
   <td>{{CompatUnknown}}</td>
   <td>{{CompatUnknown}}</td>
  </tr>
  <tr>
   <td>Monkey-patched <code>set()</code> in constructor</td>
   <td>{{CompatVersionUnknown}}</td>
   <td>{{CompatGeckoDesktop("37")}}</td>
   <td>{{CompatUnknown}}</td>
   <td>{{CompatUnknown}}</td>
   <td>{{CompatUnknown}}</td>
  </tr>
  <tr>
   <td><code>WeakMap()</code> without <code>new</code> throws</td>
   <td>{{CompatVersionUnknown}}</td>
   <td>{{CompatGeckoDesktop("42")}}</td>
   <td>{{CompatUnknown}}</td>
   <td>{{CompatUnknown}}</td>
   <td>{{CompatUnknown}}</td>
  </tr>
 </tbody>
</table>
</div>

<div id="compat-mobile">
<table class="compat-table">
 <tbody>
  <tr>
   <th>Feature</th>
   <th>Chrome for Android</th>
   <th>Firefox Mobile (Gecko)</th>
   <th>IE Mobile</th>
   <th>Opera Mobile</th>
   <th>Safari Mobile</th>
  </tr>
  <tr>
   <td>Basic support</td>
   <td>35</td>
   <td>{{CompatGeckoMobile("6.0")}}</td>
   <td>{{CompatNo}}</td>
   <td>{{CompatNo}}</td>
   <td>8</td>
  </tr>
  <tr>
   <td><code>new WeakMap(iterable)</code></td>
   <td>38</td>
   <td>{{CompatGeckoMobile("36")}}</td>
   <td>{{CompatNo}}</td>
   <td>{{CompatNo}}</td>
   <td>{{CompatNo}}</td>
  </tr>
  <tr>
   <td><code>clear()</code></td>
   <td>35</td>
   <td>{{CompatNo}} [1]</td>
   <td>{{CompatNo}}</td>
   <td>{{CompatNo}}</td>
   <td>8</td>
  </tr>
  <tr>
   <td>Constructor argument: <code>new WeakMap(null)</code></td>
   <td>{{CompatUnknown}}</td>
   <td>{{CompatGeckoMobile("37")}}</td>
   <td>{{CompatNo}}</td>
   <td>{{CompatUnknown}}</td>
   <td>{{CompatUnknown}}</td>
  </tr>
  <tr>
   <td>Monkey-patched <code>set()</code> in constructor</td>
   <td>{{CompatUnknown}}</td>
   <td>{{CompatGeckoMobile("37")}}</td>
   <td>{{CompatNo}}</td>
   <td>{{CompatUnknown}}</td>
   <td>{{CompatUnknown}}</td>
  </tr>
  <tr>
   <td><code>WeakMap()</code> without <code>new</code> throws</td>
   <td>{{CompatUnknown}}</td>
   <td>{{CompatGeckoMobile("42")}}</td>
   <td>{{CompatUnknown}}</td>
   <td>{{CompatUnknown}}</td>
   <td>{{CompatUnknown}}</td>
  </tr>
 </tbody>
</table>
</div>

<p>[1] The clear() method has been supported from version 20 until version 45 (including).</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>
 <li><a href="https://fitzgeraldnick.com/weblog/53/">Hiding Implementation Details with ECMAScript 6 WeakMaps</a></li>
 <li>{{jsxref("Map")}}</li>
 <li>{{jsxref("Set")}}</li>
 <li>{{jsxref("WeakSet")}}</li>
</ul>
Revert to this revision