aboutsummaryrefslogtreecommitdiff
path: root/files/ja/web/javascript/guide/keyed_collections/index.html
blob: 2888204bcabc4ac4029985230f399ba1cf38b0c2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
---
title: キー付きコレクション
slug: Web/JavaScript/Guide/Keyed_collections
tags:
  - Collections
  - Guide
  - JavaScript
  - Map
  - 'l10n:priority'
  - set
translation_of: Web/JavaScript/Guide/Keyed_collections
---
<div>{{jsSidebar("JavaScript Guide")}} {{PreviousNext("Web/JavaScript/Guide/Indexed_Collections", "Web/JavaScript/Guide/Working_with_Objects")}}</div>

<p class="summary">本章では、キーによって順序付けされたデータのコレクションを紹介します。Map および Set オブジェクトは挿入順に反復処理を行える要素を保持します。</p>

<h2 id="Maps" name="Maps">Map</h2>

<h3 id="Map_object" name="Map_object"><code>Map</code> オブジェクト</h3>

<p>ECMAScript 2015 で値と値とをマッピングする新しいデータ構造が導入されました。{{jsxref("Map")}} オブジェクトはシンプルなキー / バリューマップで、挿入順に要素を反復処理することができます。</p>

<p>次のコードでは <code>Map</code> を用いたいくつかの基本的な操作を表しています。また、追加の例や全ての API については、{{jsxref("Map")}} リファレンスページをご覧ください。{{jsxref("Statements/for...of","for...of")}} ループを使って、各反復処理において <code>[key, value]</code> からなる配列を返しています。</p>

<pre class="brush: js notranslate">let sayings = new Map();
sayings.set('dog', 'woof');
sayings.set('cat', 'meow');
sayings.set('elephant', 'toot');
sayings.size; // 3
sayings.get('dog'); // woof
sayings.get('fox'); // undefined
sayings.has('bird'); // false
sayings.delete('dog');
sayings.has('dog'); // false

for (let [key, value] of sayings) {
  console.log(key + ' goes ' + value);
}
// "cat goes meow"
// "elephant goes toot"

sayings.clear();
sayings.size; // 0
</pre>

<h3 id="Object_と_Map_との比較"><code>Object</code><code>Map</code> との比較</h3>

<p>伝統的に、{{jsxref("Object", "objects", "", "1")}} は文字列を値にマップするのに使われてきました。オブジェクトを使うことで、キーを値に設定し、その値を取得し、キーを削除し、キーに対応する何かが格納されているかどうかを検出することができます、しかしながら、<code>Map</code> の方が少し便利です。</p>

<ul>
 <li><code>Object</code> のキーは {{jsxref("Global_Objects/String","Strings")}} オブジェクトです、<code>Map</code> ならどんな値も使えるというのに。</li>
 <li><code>Map</code> は簡単にサイズを取得できます。<code>Object</code> はサイズを手作業で追跡する必要があります。</li>
 <li><code>Map</code> の反復処理は要素の挿入順に行われます。</li>
 <li><code>Object</code> はプロトタイプを持っているので、オブジェクトによるマップにはデフォルトキーが存在します(これは <code>map = Object.create(null)</code> を使って回避できます)。</li>
</ul>

<p><code>Map</code><code>Object</code> のどちらを使用すべきかを決めるには下記の 3 つのヒントが役立つでしょう :</p>

<ul>
 <li>実行時までキーが不明なとき、またはすべてのキーが同じ型、すべての値が同じ型のときは Object よりも Map を使用しましょう。</li>
 <li>プリミティブ値をキーとして保存する必要がある場合に Map を使用しましょう。Object はキーが数値、真偽値、もしくはいずれのプリミティブ値であるかどうかに関わらず、それぞれのキーを文字列として扱います。</li>
 <li>個々の要素を操作するロジックがある場合は、Object を使用しましょう。</li>
</ul>

<h3 id="WeakMap_object" name="WeakMap_object"><code>WeakMap</code> オブジェクト</h3>

<p>{{jsxref("WeakMap")}} オブジェクトは、<strong>キーはオブジェクトのみ</strong><strong></strong>値は任意の値にできるキー / バリューのペアからなるコレクションです。キーによるオブジェクト参照は<strong>弱く</strong>保持され、そのオブジェクトへの参照が他に存在しないときはガベージコレクション (GC) の対象になります。<code>WeakMap</code> API は <code>Map</code> API と同じです。</p>

<p><code>Map</code> オブジェクトとの違いの1つは、<code>WeakMap</code> のキーは列挙可能ではないことです(すなわち、キーのリストを取得するメソッドがありません)。もしも列挙可能であれば、リストは非決定性をもたらす、ガベージコレクションの状態に依存することになってしまいます。</p>

<p>詳細やサンプルコードについては、{{jsxref("WeakMap")}} リファレンスページの「なぜ WeakMap なのか?」もご覧ください。</p>

<p><code>WeakMap</code> オブジェクトのよくある使用方法のひとつとして、オブジェクトに対するプライベートデータの格納、あるいは実装の細部の隠蔽があります。次の例は Nick Fitzgerald 氏のブログ投稿、<a href="http://fitzgeraldnick.com/weblog/53/">"Hiding Implementation Details with ECMAScript 6 WeakMaps"</a>(ECMAScript 6 WeakMaps を使って実装の詳細を隠蔽する)です。プライベートなデータとメソッドはオブジェクトの内部に属していて、プライベートな WeakMap オブジェクトに格納されています。インスタンスから露出する全てとプロトタイプは公開されています、他の全てのものは外部よりアクセスできません。<code>privates</code> はモジュールから export されていません。</p>

<pre class="brush: js notranslate">const privates = new WeakMap();

function Public() {
  const me = {
    // ここにプライベートデータが置かれる
  };
  privates.set(this, me);
}

Public.prototype.method = function () {
  const me = privates.get(this);
  // `me` にプライベートデータを詰め込む…
};

module.exports = Public;</pre>

<h2 id="Sets" name="Sets">Set</h2>

<h3 id="Set_object" name="Set_object"><code>Set</code> オブジェクト</h3>

<p>{{jsxref("Set")}} オブジェクトは値によって構成されるコレクションです。挿入順に要素を反復処理することができます。<code>Set</code> の 1 つの値は 1 回だけ出現します; <code>Set</code> のコレクションでは値は一意です。</p>

<p>次のコードでは <code>Set</code> を用いたいくつかの基本的な操作を表しています。また、追加の例や全ての API については、{{jsxref("Set")}} リファレンスページをご覧ください。</p>

<pre class="brush: js notranslate">let mySet = new Set();
mySet.add(1);
mySet.add('some text');
mySet.add('foo');

mySet.has(1); // true
mySet.delete('foo');
mySet.size; // 2

for (let item of mySet) console.log(item);
// 1
// "some text"
</pre>

<h3 id="Converting_between_Array_and_Set" name="Converting_between_Array_and_Set"><code>Array</code><code>Set</code> 間の変換</h3>

<p>{{jsxref("Array.from")}} または <a href="/ja/docs/Web/JavaScript/Reference/Operators/Spread_operator">スプレッド構文</a> を使用して <code>Set</code> から {{jsxref("Array")}} を生成できます。また、<code>Set</code> コンストラクタを使って <code>Array</code> から <code>Set</code> へと逆変換することができます。</p>

<div class="blockIndicator note">
<p><strong>注:</strong> <code>Set</code> オブジェクトは<em>一意の値</em>を格納することにくれぐれも注意してください、重複した要素は <code>Array</code> から変換するときに削除されます。</p>
</div>

<pre class="brush: js notranslate">Array.from(mySet);
[...mySet2];

mySet2 = new Set([1, 2, 3, 4]);
</pre>

<h3 id="Array_and_Set_compared" name="Array_and_Set_compared"><code>Array</code><code>Set</code> との比較</h3>

<p>伝統的に、要素の集合は多くの状況において JavaScript の配列に格納されてきました。しかし、新しい <code>Set</code> オブジェクトにはいくつかの利点があります :</p>

<ul>
 <li>配列の {{jsxref("Array.indexOf", "indexOf")}} を使用してコレクションに要素が存在しているかどうかを調べるのは低速です。</li>
 <li><code>Set</code> オブジェクトは値を使って要素を削除できます。配列の場合には要素のインデックを使い、スプライス(該当要素を取り除いて残りをつなぎ合わせる)操作が必要です。</li>
 <li>{{jsxref("NaN")}} 値は配列の <code>indexOf</code> で検索することはできません。</li>
 <li><code>Set</code> オブジェクトは一意の値を格納します、あなたが重複を気にする必要がありません。</li>
</ul>

<h3 id="WeakSet_object" name="WeakSet_object"><code>WeakSet</code> オブジェクト</h3>

<p>{{jsxref("WeakSet")}} オブジェクトは、オブジェクトのコレクションです。<code>WeakSet</code> 内の 1 つのオブジェクトは 1 回だけ出現します; <code>WeakSet</code> コレクション内では値は一意で、オブジェクトは列挙可能ではありません。</p>

<p>{{jsxref("Set")}} オブジェクトとの主な違いは下記の通りです :</p>

<ul>
 <li><code>Set</code> とは対照的に、<code>WeakSet</code><strong>オブジェクトのみのコレクション</strong>で、任意の型の任意の値でのコレクションではありません。</li>
 <li><code>WeakSet</code><em>弱い</em><strong> </strong>: コレクションでのオブジェクトでの参照は弱く保持されています。<code>WeakSet</code> 内に格納されているオブジェクトに対する参照がなくなった場合、ガベージコレクションされます。これはまた、現在コレクション内に格納されているオブジェクトのリストがないということを表しています。<code>WeakSet</code> は列挙可能ではありません。</li>
</ul>

<p><code>WeakSet</code> オブジェクトの使用例は限定的です。メモリーリークが発生しないため、例えば、DOM 要素をキーとして使用し、監視するためにそれらにマーキングすることが安全に行なえます。</p>

<h2 id="Key_and_value_equality_of_Map_and_Set" name="Key_and_value_equality_of_Map_and_Set"><code>Map</code><code>Set</code> におけるキーと値の等値性</h2>

<p><code>Map</code> オブジェクトのキーの等値性と <code>Set</code> オブジェクトの値の等値性は両方とも、「<a href="https://tc39.github.io/ecma262/#sec-samevaluezero">same-value-zero アルゴリズム</a>」に基づいています:</p>

<ul>
 <li>等値性は原則として同値演算子 <code>===</code> のように判定されます。</li>
 <li><code>-0</code><code>+0</code> は等しいと見なします。</li>
 <li>{{jsxref("NaN")}} は(<code>===</code> とは逆に)自身と等しいと見なされます。</li>
</ul>

<p>{{PreviousNext("Web/JavaScript/Guide/Indexed_Collections", "Web/JavaScript/Guide/Working_with_Objects")}}</p>