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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
|
---
title: Map
slug: Web/JavaScript/Reference/Global_Objects/Map
tags:
- ECMAScript 2015
- JavaScript
- Map
- Reference
translation_of: Web/JavaScript/Reference/Global_Objects/Map
---
<div>{{JSRef}}</div>
<p><span class="seoSummary"><strong><code>Map</code> </strong>객체는 키-값 쌍을 저장하며 각 쌍의 삽입 순서도 기억하는 콜렉션입니다.</span> 아무 값(객체와 {{Glossary("Primitive", "원시 값")}})이라도 키와 값으로 사용할 수 있습니다.</p>
<h2 id="설명">설명</h2>
<p><code>Map</code> 객체는 요소의 삽입 순서대로 원소를 순회합니다. {{jsxref("Statements/for...of", "for...of")}} 반복문은 각 순회에서 <code>[key, value]</code>로 이루어진 배열을 반환합니다.</p>
<h3 id="키_동일성">키 동일성</h3>
<ul>
<li>키 동일성은 <a href="/ko/docs/Web/JavaScript/Equality_comparisons_and_sameness#등가0_같음"><code>sameValueZero</code></a> 알고리즘에 기반합니다.</li>
<li><code>NaN !== NaN</code>이지만, 그럼에도 <code>NaN</code>은 <code>NaN</code>과 일치한다고 간주하며, 다른 모든 값은 <code>===</code> 연산자의 결과를 따릅니다.</li>
<li>현 ECMAScript 명세는 <code>-0</code>과 <code>+0</code>을 같은 값으로 처리하지만 초기 명세에서는 그렇지 않았습니다. {{anch("브라우저 호환성")}}의 "<em>Key equality for -0 and 0</em>"을 참고하세요.</li>
</ul>
<h3 id="jsxrefObject와_Map_비교">{{jsxref("Object")}}와 <code>Map</code> 비교</h3>
<p>{{jsxref("Object")}}는 값에 키를 할당할 수 있고, 그 키로 값을 얻을 수 있고, 키를 삭제할 수 있으며 어떤 키에 값이 존재하는지 확인할 수 있다는 점에서 <code>Map</code>과 유사합니다. 이런 이유에 더해, 이전에는 내장된 대체제가 없었기 때문에, <code>Object</code>를 <code>Map</code> 대신 사용하곤 했습니다.</p>
<p>그러나 어떤 상황에선, <code>Map</code>을 선호해야 할 몇 가지 중요한 차이점이 있습니다.</p>
<table class="standard-table">
<thead>
<tr>
<th scope="row"></th>
<th scope="col"><code>Map</code></th>
<th scope="col"><code>Object</code></th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">의도치 않은 키</th>
<td><code>Map</code>은 명시적으로 제공한 키 외에는 어떤 키도 가지지 않습니다.</td>
<td>
<p><code>Object</code>는 프로토타입을 가지므로 기본 키가 존재할 수 있습니다. 주의하지 않으면 직접 제공한 키와 충돌할 수도 있습니다.</p>
<div class="blockIndicator note">
<p><strong>참고:</strong> ES5부터, 프로토타입으로 인한 키 충돌은 {{jsxref("Object.create", "Object.create(null)")}}로 해결할 수 있지만, 실제로 쓰이는 경우는 적습니다.</p>
</div>
</td>
</tr>
<tr>
<th scope="row">키 자료형</th>
<td><code>Map</code>의 키는 함수, 객체 등을 포함한 모든 값이 가능합니다.</td>
<td><code>Object</code>의 키는 반드시 {{jsxref("String")}} 또는 {{jsxref("Symbol")}}이어야 합니다.</td>
</tr>
<tr>
<th scope="row">키 순서</th>
<td>
<p><code>Map</code>의 키는 정렬됩니다. 따라서 <code>Map</code>의 순회는 삽입순으로 이뤄집니다.</p>
</td>
<td>
<p><code>Object</code>의 키는 정렬되지 않습니다.</p>
<div class="blockIndicator note">
<p><strong>참고:</strong> ECMAScript 201 이후로, 객체도 문자열과 <code>Symbol</code> 키의 생성 순서를 유지합니다. ECMEScript 2015 명세를 준수하는 JavaScript 엔진에서 문자열 키만 가진 객체를 순회하면 삽입 순을 따라갑니다.</p>
</div>
</td>
</tr>
<tr>
<th scope="row">크기</th>
<td><code>Map</code>의 항목 수는 {{jsxref("Map.prototype.size", "size")}} 속성을 통해 쉽게 알아낼 수 있습니다.</td>
<td><code>Object</code>의 항목 수는 직접 알아내야 합니다.</td>
</tr>
<tr>
<th scope="row">순회</th>
<td><code>Map</code>은 <a href="/ko/docs/Web/JavaScript/Reference/Iteration_protocols">순회 가능</a>하므로, 바로 순회할 수 있습니다.</td>
<td><code>Object</code>를 순회하려면 먼저 모든 키를 알아낸 후, 그 키의 배열을 순회해야 합니다.</td>
</tr>
<tr>
<th scope="row">성능</th>
<td>잦은 키-값 쌍의 추가와 제거에서 더 좋은 성능을 보입니다.</td>
<td>잦은 키-값 쌍의 추가와 제거를 위한 최적화가 없습니다.</td>
</tr>
</tbody>
</table>
<h2 id="생성자">생성자</h2>
<dl>
<dt>{{jsxref("Map.Map", "Map()")}}</dt>
<dd>새로운 <code>Map</code> 객체를 생성합니다.</dd>
</dl>
<h2 id="속성">속성</h2>
<dl>
<dt><code>Map.length</code></dt>
<dd>값이 0인 속성입니다.<br>
요소의 수는 {{jsxref("Map.prototype.size")}}로 알아낼 수 있습니다.</dd>
<dt>{{jsxref("Map.@@species", "get Map[@@species]")}}</dt>
<dd>파생 객체를 생성하는데 사용하는 생성자 함수입니다.</dd>
<dt>{{jsxref("Map.prototype")}}</dt>
<dd><code>Map</code> 생성자의 프로토타입을 나타냅니다. 모든 <code>Map</code> 인스턴스에 속성을 추가할 수 있습니다.</dd>
</dl>
<h2 id="Map_인스턴스"><code>Map</code> 인스턴스</h2>
<p>모든 <code>Map</code> 인스턴스는 {{jsxref("Map.prototype")}}을 상속합니다.</p>
<h3 id="속성_2">속성</h3>
<p>{{page('ko/Web/JavaScript/Reference/Global_Objects/Map/prototype','Properties')}}</p>
<h3 id="메서드">메서드</h3>
<p>{{page('ko/Web/JavaScript/Reference/Global_Objects/Map/prototype','Methods')}}</p>
<h2 id="예제">예제</h2>
<h3 id="Map_객체_사용하기"><code>Map</code> 객체 사용하기</h3>
<pre class="brush: js">let myMap = new Map()
let keyString = '문자열'
let keyObj = {}
let keyFunc = function() {}
// 값 설정
myMap.set(keyString, "'문자열'과 관련된 값")
myMap.set(keyObj, 'keyObj와 관련된 값')
myMap.set(keyFunc, 'keyFunc와 관련된 값')
myMap.size // 3
// getting the values
myMap.get(keyString) // "'문자열'과 관련된 값"
myMap.get(keyObj) // "keyObj와 관련된 값"
myMap.get(keyFunc) // "keyFunc와 관련된 값"
myMap.get('문자열') // "'문자열'과 관련된 값"
// keyString === '문자열'이기 때문
myMap.get({}) // undefined, keyObj !== {}
myMap.get(function() {}) // undefined, keyFunc !== function () {}</pre>
<h3 id="Map의_키로_NaN_사용하기"><code>Map</code>의 키로 <code>NaN</code> 사용하기</h3>
<p>{{jsxref("NaN")}}도 키로서 사용할 수 있습니다. 모든 <code>NaN</code>은 자기 자신과 동일하지 않지만(<code>NaN !== NaN</code>), <code>NaN</code>을 서로 구분할 수도 없기 때문에 아래 예제도 잘 동작합니다.</p>
<pre class="brush: js">let myMap = new Map()
myMap.set(NaN, 'not a number')
myMap.get(NaN)
// "not a number"
let otherNaN = Number('foo')
myMap.get(otherNaN)
// "not a number"</pre>
<h3 id="for..of로_Map_순회하기"><code>for..of</code><font face="Open Sans, arial, sans-serif">로 </font><code>Map</code> 순회하기</h3>
<p><code>Map</code>은 <code>for..of</code> 반복문을 사용해 순회할 수 있습니다.</p>
<pre class="brush: js">let myMap = new Map()
myMap.set(0, 'zero')
myMap.set(1, 'one')
for (let [key, value] of myMap) {
console.log(key + ' = ' + value)
}
// 0 = zero
// 1 = one
for (let key of myMap.keys()) {
console.log(key)
}
// 0
// 1
for (let value of myMap.values()) {
console.log(value)
}
// zero
// one
for (let [key, value] of myMap.entries()) {
console.log(key + ' = ' + value)
}
// 0 = zero
// 1 = one</pre>
<h3 id="forEach로_Map_순회하기"><code>forEach()</code>로 <code>Map</code> 순회하기</h3>
<p><code>Map</code>은 {{jsxref("Map.prototype.forEach", "forEach()")}} 메서드로 순회할 수 있습니다.</p>
<pre class="brush: js">myMap.forEach(function(value, key) {
console.log(key + ' = ' + value)
})
// 0 = zero
// 1 = one</pre>
<h3 id="Array_객체와의_관계"><code>Array</code> 객체와의 관계</h3>
<pre class="brush: js">let kvArray = [['key1', 'value1'], ['key2', 'value2']]
// Use the regular Map constructor to transform a 2D key-value Array into a map
let myMap = new Map(kvArray)
myMap.get('key1') // returns "value1"
// Use Array.from() to transform a map into a 2D key-value Array
console.log(Array.from(myMap)) // Will show you exactly the same Array as kvArray
// A succinct way to do the same, using the spread syntax
console.log([...myMap])
// Or use the keys() or values() iterators, and convert them to an array
console.log(Array.from(myMap.keys())) // ["key1", "key2"]</pre>
<h2 id="명세">명세</h2>
<table class="standard-table">
<tbody>
<tr>
<th scope="col">Specification</th>
</tr>
<tr>
<td>{{SpecName('ESDraft', '#sec-map-objects', 'Map')}}</td>
</tr>
</tbody>
</table>
<h2 id="브라우저_호환성">브라우저 호환성</h2>
<p>{{Compat("javascript.builtins.Map")}}</p>
<h2 id="같이_보기">같이 보기</h2>
<ul>
<li>{{jsxref("Set")}}</li>
<li>{{jsxref("WeakMap")}}</li>
<li>{{jsxref("WeakSet")}}</li>
</ul>
|