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
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
|
---
title: Map
slug: Web/JavaScript/Reference/Global_Objects/Map
tags:
- ECMAScript 2015
- JavaScript
- Map
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>
<pre class="syntaxbox">new Map([<em>iterable</em>])</pre>
<h3 id="Параметры">Параметры</h3>
<dl>
<dt><code>iterable</code></dt>
<dd>Массив или любой другой <a href="/ru/docs/Web/JavaScript/Reference/Iteration_protocols">итерируемый</a> объект чьими элементами являются пары ключ-значение (массивы из двух элементов, например <code>[[ 1, 'one' ],[ 2, 'two' ]]</code>). Все пары ключ-значение будут добавлены в новый экземпляр <code>Map</code>; <code>null</code> расценивается как <code>undefined</code>.</dd>
</dl>
<h2 id="Описание">Описание</h2>
<p>Объект <code>Map</code> итерируется в порядке вставки его элементов — цикл {{jsxref("Statements/for...of", "for...of")}} будет возвращать массив <code>[key, value]</code> на каждой итерации.</p>
<h3 id="Key_equality">Key equality</h3>
<p>Сравнение ключей основано на алгоритме "{{Glossary("SameValueZero", "SameValueZero")}}": <code>NaN</code> равно <code>NaN</code> (несмотря на то, что <code>NaN !== NaN</code>), все другие значения рассматриваются равными исходя из семантики оператора строгого равенства <code>===</code>. В текущей спецификации ECMAScript <code>-0</code> и <code>+0</code> принимаются равными, но в ранних версиях обсуждения это было не так (см. "Value equality for -0 and 0" в таблице <a href="#Browser_compatibility">совместимости с браузерами</a>).</p>
<h3 id="Сравнение_Объектов_и_Map">Сравнение Объектов и Map</h3>
<p>Объекты похожи на <code>Map</code> в том, что оба позволяют устанавливать значения по ключам, получать эти значения, удалять ключи и проверять их наличие. В связи с этим (и потому, что не было встроенных альтернатив), {{jsxref("Object", "Объекты")}} исторически использовались как <code>Map</code>. Однако, у них есть ряд отличий, который даёт преимущества <code>Map</code> в ряде случаев:</p>
<ul>
<li>Ключами {{jsxref("Object", "Объекта")}} выступают {{jsxref("String", "Строки")}} и {{jsxref("Symbol", "Символы")}}, в то время как любое значение может быть ключом <code>Map</code>, включая {{jsxref("Function", "функции")}}, {{jsxref("Object", "объекты")}} и {{Glossary("Primitive", "примитивы")}}.</li>
<li>В отличие от {{jsxref("Object", "Объектов")}}, ключи в <code>Map</code> упорядочены. Таким образом, во время итерации <code>Map</code>, ключи возвращаются в порядке вставки.</li>
<li>Вы легко можете получить количество элементов в <code>Map</code> с помощью свойства <code>size</code>, в то время как количество элементов {{jsxref("Object", "Объекта")}} может быть определено только вручную.</li>
<li><code>Map</code> - <a href="/en-US/docs/Web/JavaScript/Guide/iterable">итерируемый</a> объект и может быть итерирован напрямую, в то время как {{jsxref("Object", "Объект")}} требует ручного получения списка ключей и их итерации.</li>
<li>{{jsxref("Object", "Объект")}} имеет прототип и поэтому имеет стандартный набор ключей, который, при неосторожности, может пересекаться с вашими ключами. С момента выхода ES5 это может быть изменено с помощью <code>map = Object.create(null)</code>.</li>
<li><code>Map</code> может иметь более высокую производительность в случаях частого добавления или удаления ключей.</li>
</ul>
<h2 id="Свойства">Свойства</h2>
<dl>
<dt><code>Map.length</code></dt>
<dd>Значение свойства <code>length</code> всегда равно 0.</dd>
<dd>Чтобы узнать количество элементов в <code>Map</code> - используйте {{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>
<dl>
<dt><code>Map.prototype.constructor</code></dt>
<dd>Возвращает функцию, которая создала прототип экземпляра. Это функция <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map" title="The Map object holds key-value pairs and remembers the original insertion order of the keys."><code>Map</code></a> по умолчанию.</dd>
<dt><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/size" title="The size accessor property returns the number of elements in a Map object."><code>Map.prototype.size</code></a></dt>
<dd>Возвращает количество пар ключ/значение в объекте <code>Map</code>.</dd>
</dl>
<h3 id="Методы">Методы</h3>
<dl>
<dt><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/clear" title="The clear() method removes all elements from a Map object."><code>Map.prototype.clear()</code></a></dt>
<dd>Удаляет все пары ключ / значение из объекта <code>Map</code>.</dd>
<dt><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/delete" title="The delete() method removes the specified element from a Map object by key."><code>Map.prototype.delete(key)</code></a></dt>
<dd>Возвращает <code>true</code>, если элемент в объекте <code>Map</code> существовал и был удалён, или false, если элемент не существует. <code>Map.prototype.has(key)</code> вернёт <code>false</code> позже.</dd>
<dt><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/entries" title="The entries() method returns a new Iterator object that contains the [key, value] pairs for each element in the Map object in insertion order."><code>Map.prototype.entries()</code></a></dt>
<dd>Возвращает новый объект <code>Iterator</code> который содержит <strong>массив</strong> <strong><code>[key, value]</code></strong> для каждого элемента в объекте <code>Map</code> в порядке вставки.</dd>
<dt><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/forEach" title="The forEach() method executes a provided function once per each key/value pair in the Map object, in insertion order."><code>Map.prototype.forEach(callbackFn[, thisArg])</code></a></dt>
<dd>Вызывает callbackFn один раз для каждой пары ключ-значение, присутствующей в объекте <code>Map</code>, в порядке вставки. Если для thisArg предоставляется параметр для forEach, он будет использоваться как значение this для каждого колбэка.</dd>
<dt><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/get" title="The get() method returns a specified element from a Map object."><code>Map.prototype.get(key)</code></a></dt>
<dd>Возвращает значение связанное с <code>key</code>, или <code>undefined</code> если его нет.</dd>
<dt><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/has" title="The has() method returns a boolean indicating whether an element with the specified key exists or not."><code>Map.prototype.has(key)</code></a></dt>
<dd>Возвращает логическое значение, подтверждающее, было ли значение связано с <code>key</code> в объекте <code>Map</code> или нет.</dd>
<dt><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/keys" title="The keys() method returns a new Iterator object that contains the keys for each element in the Map object in insertion order."><code>Map.prototype.keys()</code></a></dt>
<dd>Возвращает новый объект <code>Iterator</code> содержащий ключи для каждого элемента в объекте <code>Map</code> в порядке вставки.</dd>
<dt><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/set" title="The set() method adds or updates an element with a specified key and a value to a Map object."><code>Map.prototype.set(key, value)</code></a></dt>
<dd>Устанавливает значение для <code>key</code> в объекте <code>Map</code>. Возвращает объект <code>Map</code>.</dd>
<dt><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/values" title="The values() method returns a new Iterator object that contains the values for each element in the Map object in insertion order."><code>Map.prototype.values()</code></a></dt>
<dd>Возвращает новый объект <code>Iterator</code> который содержит значения для каждого элемента в объекте <code>Map</code> в порядке вставки.</dd>
<dt><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/@@iterator" title="The initial value of the @@iterator property is the same function object as the initial value of the entries method."><code>Map.prototype[@@iterator]()</code></a></dt>
<dd>Возвращает новый объект <code>Iterator</code> который содержит массив<strong> <code>[key, value]</code></strong> для каждого элемента в объекте <code>Map</code> в порядке вставки.</dd>
</dl>
<h2 id="Примеры">Примеры</h2>
<h3 id="Использование_объекта_Map">Использование объекта <code>Map</code></h3>
<pre class="brush: js">const myMap = new Map();
const keyObj = {},
keyFunc = function () {},
keyString = 'a string';
// задание значений
myMap.set(keyString, 'value associated with “a string”');
myMap.set(keyObj, 'value associated with keyObj');
myMap.set(keyFunc, 'value associated with keyFunc');
myMap.size; // 3
// получение значений
myMap.get(keyString); // value associated with “a string”
myMap.get(keyObj); // value associated with keyObj
myMap.get(keyFunc); // value associated with keyFunc
myMap.get('a string'); // "value associated with 'a string'"
// потому что keyString === 'a string'
myMap.get({}); // undefined, потому что <span style="font-size: 1rem;">keyObj !== {} ({} — это литеральная нотация конструктора класса Object)</span>
myMap.get(function() {}) // undefined, потому что <span style="font-size: 1rem;">keyFunc !== function () {}</span>
</pre>
<h3 id="Использование_NaN_в_качестве_ключей_Map">Использование <code>NaN</code> в качестве ключей <code>Map</code></h3>
<p><code>NaN</code> может быть использован в качестве ключа. Несмотря на то, что <code>NaN</code> не равен самому себе (<code>NaN !== NaN</code> вернёт true), следующий пример работает, потому что <code>NaN</code> обрабатывается особым образом:</p>
<pre class="brush: js">const myMap = new Map();
myMap.set(NaN, 'not a number');
myMap.get(NaN); // not a number
const otherNaN = Number('foo');
myMap.get(otherNaN); // not a number
</pre>
<h3 id="Итерация_Map_при_помощи_for..of">Итерация <code>Map</code> при помощи <code>for..of</code></h3>
<p><code>Map</code> может быть итерирован с помощью <code>for..of</code>:</p>
<pre class="brush: js">const myMap = new Map();
myMap.set(0, 'zero');
myMap.set(1, 'one');
for (var [key, value] of myMap) {
console.log(key + ' = ' + value);
}
// 0 = zero
// 1 = one
for (var key of myMap.keys()) {
console.log(key);
}
// 0
// 1
for (var value of myMap.values()) {
console.log(value);
}
// zero
// one
for (var [key, value] of myMap.entries()) {
console.log(key + ' = ' + value);
}
// 0 = zero
// 1 = one
</pre>
<h3 id="Итерация_Map_при_помощи_forEach">Итерация <code>Map</code> при помощи <code>forEach()</code></h3>
<p><code>Map</code> может быть итерирован с помощью метода <code>forEach()</code>:</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">const kvArray = [['key1', 'value1'], ['key2', 'value2']];
// Используйте конструктор Map для преобразования двумерных массивов в Map
const myMap = new Map(kvArray);
myMap.get('key1'); // вернёт “value1”
// Используйте функцию Array.from для трансформации Map в двумерный key-value массив
console.log(Array.from(myMap)); // Выведет точно такой же массив как kvArray
// Или используйте итераторы keys или values чтобы преобразовать ключи или значения в массивы
console.log(Array.from(myMap.keys())); // Выведет ['key1', 'key2']
</pre>
<h3 id="Клонирование_и_слияние_Map">Клонирование и слияние <code>Map</code></h3>
<p> Равно как и {{jsxref("Array", "Массивы")}}, <code>Map</code> могут быть клонированы:</p>
<pre class="brush: js">const original = new Map([
[1, 'one']
]);
const clone = new Map(original);
console.log(clone.get(1)); // one
console.log(original === clone); // false.</pre>
<p>Следует помнить, что <em>данные</em> не клонируются.</p>
<p><code>Map</code> могут быть слиты, с сохранением уникальности ключей:</p>
<pre class="brush: js">const first = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);
const second = new Map([
[1, 'uno'],
[2, 'dos']
]);
// Слияние двух Map. Взят будет последний повторившийся ключ.
// Оператор Spread по сути преобразует Map в массив
const merged = new Map([...first, ...second]);
console.log(merged.get(1)); // uno
console.log(merged.get(2)); // dos
console.log(merged.get(3)); // three</pre>
<p>Map могут быть слиты и с {{jsxref("Array", "Массивами")}}:</p>
<pre class="brush: js">const first = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);
const second = new Map([
[1, 'uno'],
[2, 'dos']
]);
// Слияние Map и массива. Как и при слиянии двух Map - взят будет последний повторившийся ключ.
const merged = new Map([...first, ...second, [1, 'eins']]);
console.log(merged.get(1)); // eins
console.log(merged.get(2)); // dos
console.log(merged.get(3)); // three</pre>
<h2 id="Спецификации">Спецификации</h2>
<table class="standard-table">
<tbody>
<tr>
<th scope="col">Спецификация</th>
<th scope="col">Статус</th>
<th scope="col">Комментарий</th>
</tr>
<tr>
<td>{{SpecName('ES2015', '#sec-map-objects', 'Map')}}</td>
<td>{{Spec2('ES2015')}}</td>
<td>Initial definition.</td>
</tr>
<tr>
<td>{{SpecName('ESDraft', '#sec-map-objects', 'Map')}}</td>
<td>{{Spec2('ESDraft')}}</td>
<td></td>
</tr>
</tbody>
</table>
<h2 id="Совместимость_с_браузерами">Совместимость с браузерами</h2>
<div class="hidden">Таблица совместимости на данной странице сгенерирована из структурированных данных. Если вы хотите дополнить данные - пожалуйста клонируйте <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> и пришлите нам свой пулреквест.</div>
<p>{{Compat("javascript.builtins.Map")}}</p>
<h2 id="Смотрите_также">Смотрите также</h2>
<ul>
<li><a class="link-https" href="https://bugzilla.mozilla.org/show_bug.cgi?id=697479">Map и Set баг в Mozilla</a></li>
<li><a class="external" href="http://wiki.ecmascript.org/doku.php?id=harmony:simple_maps_and_sets">Предложение ECMAScript Harmony</a></li>
<li>{{jsxref("Set")}}</li>
<li>{{jsxref("WeakMap")}}</li>
<li>{{jsxref("WeakSet")}}</li>
</ul>
|