mozilla

Revision 336515 of WeakMap

  • リビジョンの URL スラグ: JavaScript/Reference/Global_Objects/WeakMap
  • リビジョンのタイトル: WeakMap
  • リビジョンの ID: 336515
  • 作成日:
  • 作成者: saneyuki_s
  • 現行リビジョン いいえ
  • コメント

このリビジョンの内容

{{ Harmony() }}

イントロダクション

WeakMap は、オブジェクトをキーにする、キー/バリュー型のマップです。

API

メソッド 詳細
myWeakMap.get(key [, defaultValue]) key オブジェクトに関連付けられた値を返します。関連付けられた値が存在しない場合、defaultValue が返ります。
myWeakMap.set(key, value) myWeakMap に於いて、 key オブジェクトと値を関連付けます。undefined が返ります。
myWeakMap.has(key) myWeakMap に於いて、key オブジェクトに関連する値が設定されているかどうかを検証した真偽値が返ります。
myWeakMap.delete(key) key オブジェクトに関連付けられた値を削除します。このメソッドが呼ばれた後では、myWeakMap.has(key)false を返すことになります。
myWeakMap.clear() myWeakMap の値を全て空にします。undefined が返ります。

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); // 値は(オブジェクトまたは関数を含む)何であってもかまいません
wm2.set(o3, undefined);
wm2.set(wm1, wm2); // キーも値もどんなオブジェクトでもかまいません。WeakMap であってもよいのです!

wm1.get(o2); // "azerty"
wm2.get(o2); // wm2 には o2 に関連付けられた値が無い為、undefined が返ってきます
wm2.get(o3); // 値が undefined と関連付けられている為、undefined が返ってきます

wm1.has(o2); // true
wm2.has(o2); // false
wm2.has(o3); // true (値が関連付けられているならば、たとえ値が 'undefined' であっても true となります)

wm3.set(o1, 37);
wm3.get(o1); // 37
wm3.clear();
wm3.get(o1); // undefined, wm3 は clear されたため o1 に関連する値は持っていません

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

なぜ WeakMap なのか?

経験豊富な JavaScript プログラマであれば、4 つの API メソッドから共有される 2 つの配列( 1 つはキー用、もう 1 つはバリュー用)を用いることで、この API を JavaScript で実装することが可能であることに気づくでしょう。そうした実装では、主に 2 つの不都合が生じることとなります。1 つ目の不都合は、{{ Gengoheiki("探索の計算量が O(n) となること", "O(n) search") }}(n はマップ中におけるキーの数を表す)。もう 1 つの不都合はメモリリークの問題です。(2 つの配列を使って)マップを自作した場合、キーの配列はキーとしたオブジェクトへの参照を保持し続けるでしょう。従って、それらのキーとなったオブジェクトはガベージコレクションの対象から外されることとなります。ネイティブな WeakMap では、キーとなるオブジェクトに対しては"弱い"参照が保持されます。これにより、キーとなったオブジェクトへの参照が他に存在しない場合に、そのオブジェクトはガベージコレクションの対象に含まれるようになります。

弱参照を用いるため、WeakMap のキーは列挙できません(つまり、キーの一覧を取得するメソッドは存在しません)。キーの一覧はガベージコレクションに依存することになり、非決定性が生まれます。キーの一覧が必要な場合は、あなた自身の手でキーの一覧を管理することになります。ECMAScript proposal では、弱参照を使用しない且つキーの列挙が可能な、単純なセットやマップの導入も目標とされていることを付け加えておきます。

標準仕様

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

ブラウザ互換性

{{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}}

関連

このリビジョンのソースコード

<p>{{ Harmony() }}</p>
<h2 id=".E3.82.A4.E3.83.B3.E3.83.88.E3.83.AD.E3.83.80.E3.82.AF.E3.82.B7.E3.83.A7.E3.83.B3">イントロダクション</h2>
<p>WeakMap は、オブジェクトをキーにする、キー/バリュー型のマップです。</p>
<h2 id="API">API</h2>
<table class="standard-table">
  <tbody>
    <tr>
      <th>メソッド</th>
      <th>詳細</th>
    </tr>
    <tr>
      <td><code>myWeakMap.get(key [, defaultValue])</code></td>
      <td><code>key</code> オブジェクトに関連付けられた値を返します。関連付けられた値が存在しない場合、<code>defaultValue</code> が返ります。</td>
    </tr>
    <tr>
      <td><code>myWeakMap.set(key, value)</code></td>
      <td><code>myWeakMap</code> に於いて、 <code>key</code> オブジェクトと値を関連付けます。<code>undefined</code> が返ります。</td>
    </tr>
    <tr>
      <td><code>myWeakMap.has(key)</code></td>
      <td><code>myWeakMap</code> に於いて、<code>key</code> オブジェクトに関連する値が設定されているかどうかを検証した真偽値が返ります。</td>
    </tr>
    <tr>
      <td><code>myWeakMap.delete(key)</code></td>
      <td><code>key</code> オブジェクトに関連付けられた値を削除します。このメソッドが呼ばれた後では、<code>myWeakMap.has(key)</code> は <code>false</code> を返すことになります。</td>
    </tr>
    <tr>
      <td><code>myWeakMap.clear()</code></td>
      <td><code>myWeakMap</code> の値を全て空にします。<code>undefined</code> が返ります。</td>
    </tr>
  </tbody>
</table>
<h2 id=".E4.BE.8B">例</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); // 値は(オブジェクトまたは関数を含む)何であってもかまいません
wm2.set(o3, undefined);
wm2.set(wm1, wm2); // キーも値もどんなオブジェクトでもかまいません。WeakMap であってもよいのです!

wm1.get(o2); // "azerty"
wm2.get(o2); // wm2 には o2 に関連付けられた値が無い為、undefined が返ってきます
wm2.get(o3); // 値が undefined と関連付けられている為、undefined が返ってきます

wm1.has(o2); // true
wm2.has(o2); // false
wm2.has(o3); // true (値が関連付けられているならば、たとえ値が 'undefined' であっても true となります)

wm3.set(o1, 37);
wm3.get(o1); // 37
wm3.clear();
wm3.get(o1); // undefined, wm3 は clear されたため o1 に関連する値は持っていません

wm1.has(o1);   // true
wm1.delete(o1);
wm1.has(o1);   // false
</pre>
<h2 id=".E3.81.AA.E3.81.9C_WeakMap_.E3.81.AA.E3.81.AE.E3.81.8B.3F">なぜ <em>Weak</em>Map なのか?</h2>
<p>経験豊富な JavaScript プログラマであれば、4 つの API メソッドから共有される 2 つの配列( 1 つはキー用、もう 1 つはバリュー用)を用いることで、この API を JavaScript で実装することが可能であることに気づくでしょう。そうした実装では、主に 2 つの不都合が生じることとなります。1 つ目の不都合は、{{ Gengoheiki("探索の計算量が O(n) となること", "O(n) search") }}(n はマップ中におけるキーの数を表す)。もう 1 つの不都合はメモリリークの問題です。(2 つの配列を使って)マップを自作した場合、キーの配列はキーとしたオブジェクトへの参照を保持し続けるでしょう。従って、それらのキーとなったオブジェクトはガベージコレクションの対象から外されることとなります。ネイティブな WeakMap では、キーとなるオブジェクトに対しては"弱い"参照が保持されます。これにより、キーとなったオブジェクトへの参照が他に存在しない場合に、そのオブジェクトはガベージコレクションの対象に含まれるようになります。</p>
<p>弱参照を用いるため、WeakMap のキーは列挙できません(つまり、キーの一覧を取得するメソッドは存在しません)。キーの一覧はガベージコレクションに依存することになり、非決定性が生まれます。キーの一覧が必要な場合は、あなた自身の手でキーの一覧を管理することになります。<a class="external" href="http://wiki.ecmascript.org/doku.php?id=harmony:simple_maps_and_sets">ECMAScript proposal</a> では、弱参照を使用しない且つキーの列挙が可能な、単純なセットやマップの導入も目標とされていることを付け加えておきます。</p>
<h2 id="Specifications" name="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">ブラウザ互換性</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>
<h2 id=".E9.96.A2.E9.80.A3">関連</h2>
<ul>
  <li><a class="link-https" href="https://bugzilla.mozilla.org/show_bug.cgi?id=547941">WeakMap に関する bugzilla.mozilla.org 上のbug</a></li>
</ul>
このリビジョンへ戻す