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
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
|
---
title: Array.prototype.map()
slug: Web/JavaScript/Reference/Global_Objects/Array/map
tags:
- Array
- ECMAScript5
- JavaScript
- Масив
- метод
- поліфіл
- прототип
translation_of: Web/JavaScript/Reference/Global_Objects/Array/map
---
<div>{{JSRef}}</div>
<p>Метод <code><strong>map()</strong></code> <strong>створює новий масив</strong> з результатами виклику наданої функції на кожному елементі масиву, який викликав метод.</p>
<p>{{EmbedInteractiveExample("pages/js/array-map.html")}}</p>
<div class="hidden">
<p>The source for this interactive example is stored in a GitHub repository. If you'd like to contribute to the interactive examples project, please clone <a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> and send us a pull request." </p>
</div>
<h2 id="Синтаксис">Синтаксис</h2>
<pre class="brush: js"><var>var new_array = arr.map(function callback(currentValue[, index[, array]]) {
// Повернути елемент нового масиву new_array
}[, thisArg])</var></pre>
<h3 id="Параметри">Параметри</h3>
<dl>
<dt><code>callback</code></dt>
<dd>Функція, яка повертає елемент нового масиву. Приймає три аргументи:</dd>
<dd>
<dl>
<dt><code>currentValue</code></dt>
<dd>Поточний елемент масиву.</dd>
<dt><code>index</code>{{optional_inline}}</dt>
<dd>Індекс поточного елементу масиву</dd>
<dt><code>array</code>{{optional_inline}}</dt>
<dd>Сам масив, на якому був викликаний <code>map</code>.</dd>
</dl>
</dd>
<dt><code>thisArg</code>{{optional_inline}}</dt>
<dd>Значення, що буде використане як <code>this</code> при виконанні <code>callback</code>.</dd>
</dl>
<h3 id="Значення_що_повертається_(return_value)">Значення, що повертається (return value)</h3>
<p>Новий масив, кожен елемент якого є результатом функції <code>callback</code>.</p>
<h2 id="Опис">Опис</h2>
<p>Метод <code>map</code> викликає передану <code>callback-функцію</code> <strong>один раз для кожного елементу</strong> масиву, в заданому порядку, та створює новий масив з результатів. <code>callback</code> викликаться тільки для індексів яким відповідають значення, включно з <a href="/uk/docs/Web/JavaScript/Reference/Global_Objects/undefined">undefined</a>. Функція не викликається для елеметів значення яких відсутні (мається на увазі, індекси які не були явно задані, які були видалені або яким не було присвоєне значення).</p>
<p>Остільки <code>map</code> створює новий масив, викликати його, якщо ви не збираєтесь використовувати повернений масив, є антишаблоном; скористайтесь натомість <a href="https://developer.mozilla.org/uk/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach"><code>forEach</code></a> або <a href="https://developer.mozilla.org/uk/docs/Web/JavaScript/Reference/Statements/for...of"><code>for-of</code></a>. Ознаки того, що вам не підходить метод <code>map</code>: А) Ви не використовуєте масив, який він повертає, і/або Б) Ви не повертаєте значення у функції <code>callback</code>.</p>
<p><code>callback</code> викликається з трьома аргументами: значення елемента, індекс елемента, та масив на якому операцію було викликано.</p>
<p>Якщо <code>thisArg</code> параметр переданий в <code>map</code>, він буде використовуватись як ключове слово this для <code>callback-функції</code>. В іншому випадку, значення {{jsxref("undefined")}} буде використане як <code>this</code>. Значення this, яке спостерігається в callback-функції, в кінцевому рахунку визначається згідно <a href="/uk/docs/Web/JavaScript/Reference/Operators/this">звичайних правил для визначення this, видимого з функції</a>.</p>
<p><code>map</code> не змінює масив, на якому був викликаний (хоча <code>callback</code>, якщо був викликаний, може змінити).</p>
<p>Діапазон елементів, які обробляє метод map, визначений до того як callback-функція буде визвана вперше. Елементи які будуть додані до масиву після виклику map, не будуть оброблені callback-функцією. Якщо існуючі в масиві елементи змінені або видалені, їхні значення при потраплянні в callback-функцію, будуть такими якими вони є на той час коли map обробляє їх. Елементи які були видалені до і після того як map був визваний, ігноруються. </p>
<p>Згідно з алгоритмом, визначеним у специфікації, якщо масив на якому було викликано map, розріджений, то масив на виході теж буде розрідженим, залишаючи ті ж самі індекси пустими.</p>
<h2 id="Приклади">Приклади</h2>
<h3 id="Перетворення_масиву_з_числами_в_масив_квадратних_коренів">Перетворення масиву з числами в масив квадратних коренів</h3>
<p>Наступний код бере масив з числами і створює новий масив, який складається з квадратних коренів чисел з першого масиву.</p>
<pre class="brush: js">var numbers = [1, 4, 9];
var roots = numbers.map(function(num) {
return Math.sqrt(num)
});
// roots тепер [1, 2, 3]
// numbers залишається [1, 4, 9]
</pre>
<h3 id="Використання_map_для_переформатування_об'єктів_в_масиві">Використання map для переформатування об'єктів в масиві</h3>
<p>Наступний код використовує масив з об'єктами щоб створити новий масив з переформатованими об'єктами.</p>
<pre class="brush: js">var kvArray = [{key:1, value:10},
{key:2, value:20},
{key:3, value: 30}];
var reformattedArray = kvArray.map(obj =>{
var rObj = {};
rObj[obj.key] = obj.value;
return rObj;
});
// reformattedArray тепер [{1:10}, {2:20}, {3:30}],
// kvArray залишається:
// [{key:1, value:10},
// {key:2, value:20},
// {key:3, value: 30}]
</pre>
<h3 id="Перетворення_масиву_чисел_використовуючи_функцію_з_аргументом">Перетворення масиву чисел використовуючи функцію з аргументом</h3>
<p>Наступний код показує як map працює коли функція що потребує один аргумент, використовує його. Аргумент буде автоматично присвоєний з кожного елементу масиву коли map буде проходитись по оригінальному масиву..</p>
<pre class="brush: js">var numbers = [1, 4, 9];
var doubles = numbers.map(function(num) {
return num * 2;
});
// doubles тепер [2, 8, 18]
// numbers залишається [1, 4, 9]
</pre>
<h3 id="Загальне_використання_map">Загальне використання <code>map</code></h3>
<p>Цей приклад показує як використовувати map на рядках ({{jsxref("String")}}) щоб отримати масив байтів в ASCII кодуванні яке відображає значення літер:</p>
<pre class="brush: js">var map = Array.prototype.map;
var a = map.call('Hello World', function(x) {
return x.charCodeAt(0);
});
// a тепер дорівнює [72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]
</pre>
<h3 id="Загальне_використання_map_з_querySelectorAll">Загальне використання <code>map</code> з <code>querySelectorAll</code></h3>
<p>Даний приклад показує, як виконати перебір набору об'єктів, отриманих методом <code>querySelectorAll</code>. Тому що метод <code>querySelectorAll</code> повертає <strong><em>NodeList</em></strong>, який є колекцією об'єктів.</p>
<p>У даному випадку ми повертаємо значення всіх вибраних опцій на екрані:</p>
<pre class="brush: js">var elems = document.querySelectorAll('select option:checked');
var values = Array.prototype.map.call(elems, function(obj) {
return obj.value;
});
</pre>
<p>Це простіше зробити методом {{jsxref("Array.from()")}}.</p>
<h3 id="Хитрий_спосіб_використання">Хитрий спосіб використання</h3>
<p>(<a href="http://www.wirfs-brock.com/allen/posts/166">натхненний цим блог-постом</a>)</p>
<p>Загальноприйнято використовувати функцію callback з одним аргументом (елемент по якому проходиться функція). Деякі функції також використовуються з одним аргументом, хоча можуть приймати і більше додаткових аргументів, що не є обов'язковими. Це може призводити до неочікуваної поведінки.</p>
<p>Розглянемо:</p>
<pre class="brush: js">["1", "2", "3"].map(parseInt);</pre>
<p>Хоча можна було б очікувати <code>[1, 2, 3]</code>, справжнім результатом буде <code>[1, NaN, NaN]</code>.</p>
<p>Метод <code>parseInt</code> часто використовується з одним аргументом, але приймає два. Перший - це вираз, а другий - основа системи числення для функції зворотного виклику. <code>Array.prototype.map</code> передає 3 аргументи:</p>
<ul>
<li>елемент</li>
<li>індекс</li>
<li>масив</li>
</ul>
<p>Третій аргумент ігнорується методом parseInt, <u>але не другий</u>, звідси й можлива плутанина. Ось стислий огляд кроків перебору:</p>
<pre class="brush: js">// parseInt(string, radix) -> map(parseInt(value, index))
/* first iteration (index is 0): */ parseInt("1", 0); // 1
/* second iteration (index is 1): */ parseInt("2", 1); // NaN
/* third iteration (index is 2): */ parseInt("3", 2); // NaN</pre>
<p>Поговоримо про рішення.</p>
<pre class="brush: js">function returnInt(element) {
return parseInt(element, 10);
}
['1', '2', '3'].map(returnInt); // [1, 2, 3]
// Результатом є масив чисел (як і очікувалось)
// Те саме, але з використанням лаконічного стрілкового синтаксису
['1', '2', '3'].map( str => parseInt(str) );
// Простіший спосіб досягти вищевказаного
['1', '2', '3'].map(Number); // [1, 2, 3]
// На відміну від parseInt(), Number() також поверне десятковий або експоненціальний запис:
['1.1', '2.2e2', '3e300'].map(Number); // [1.1, 220, 3e+300]
// Для порівняння, якщо використати parseInt() для попереднього масиву:
['1.1', '2.2e2', '3e300'].map( str => parseInt(str) ); // [1, 2, 3]</pre>
<p>Ще один варіант результату метода map, що викликається з parseInt в якості параметра, виглядає наступним чином:</p>
<pre class="brush: js">var xs = ['10', '10', '10'];
xs = xs.map(parseInt);
console.log(xs);
// Результат 10,NaN,2 може бути неочікуваним, з огляду вищеописане.</pre>
<h3 id="Масив_містить_значення_undefined">Масив містить значення undefined</h3>
<p>Коли повертається undefined або нічого не повертається:</p>
<pre class="brush: js">var numbers = [1, 2, 3, 4];
var filteredNumbers = numbers.map(function(num, index) {
if(index < 2) {
return num;
}
});
// filteredNumbers дорівнює [1, 2, undefined, undefined]
// numbers досі дорівнює [1, 2, 3, 4]</pre>
<h2 id="Поліфіл">Поліфіл</h2>
<p><font face="Consolas, Liberation Mono, Courier, monospace">Метод <code>map</code> </font>був доданий до ECMA-262 стандарту в 5-тій редакції; тому він може бути присутнім не у всіх реалізаціях стандарту. Ви можете обійти це, вставляючи наступний код на початок вашого скритпу, дозволяючи використовувати map в реалізаціях які ще його не підтримують. Цей алгоритм є точно таким який вказаний в ECMA-262, 5му виданні, передбачаючи що {{jsxref("Object")}}, {{jsxref("TypeError")}}, і {{jsxref("Array")}} мають свої власні значення і що <code>callback.call</code> обчислює початкове значення <code>{{jsxref("Function.prototype.call")}}</code>.</p>
<pre class="brush: js">// Функціональні кроки ECMA-262, версія 5, 15.4.4.19
// Довідка: http://es5.github.io/#x15.4.4.19
if (!Array.prototype.map) {
Array.prototype.map = function(callback, thisArg) {
var T, A, k;
if (this == null) {
throw new TypeError(' this is null or not defined');
}
// 1. Нехай O дорівнює результату виклику ToObject з |this|
// в якості аргументу.
var O = Object(this);
// 2. Нехай lenValue дорівнює результату виклику внутрішнього методу O
// Get з аргументом "length".
// 3. Нехай len дорівнює ToUint32(lenValue).
var len = O.length >>> 0;
// 4. Якщо IsCallable(callback) дорівнює false, викинути виняток TypeError.
// Див.: http://es5.github.com/#x9.11
if (typeof callback !== 'function') {
throw new TypeError(callback + ' is not a function');
}
// 5. Якщо надано thisArg, нехай T дорівнює thisArg; інакше нехай T дорівнює undefined.
if (arguments.length > 1) {
T = thisArg;
}
// 6. Нехай A дорівнює новому масиву, створеному виразом new Array(len),
// де Array - це стандартний вбудований конструктор з таким ім'ям,
// а len дорівнює значенню len.
A = new Array(len);
// 7. Нехай k дорівнює 0
k = 0;
// 8. Повторювати, доки k < len
while (k < len) {
var kValue, mappedValue;
// а. Нехай Pk дорівнює ToString(k).
// Цей метод неявно застосовується до лівого операнда оператора in
// б. Нехай kPresent дорівнює результату виклику внутрішнього методу O
// HasProperty з аргументом Pk.
// Цей крок можна об'єднати з в
// в. Якщо kPresent дорівнює true, тоді
if (k in O) {
// і. Нехай kValue дорівнює результату виклику внутрішнього методу O
// Get з аргументом Pk.
kValue = O[k];
// ii. Нехай mappedValue дорівнює результату виклику внутрішнього
// методу callback Call з T у якості значення this та списком
// аргументів, що містить kValue, k та O.
mappedValue = callback.call(T, kValue, k, O);
// iii. Викликати внутрішній метод A DefineOwnProperty з аргументами
// Pk, Property Descriptor
// { Value: mappedValue,
// Writable: true,
// Enumerable: true,
// Configurable: true },
// та false.
// У переглядачах, що підтримують Object.defineProperty, використовуйте:
// Object.defineProperty(A, k, {
// value: mappedValue,
// writable: true,
// enumerable: true,
// configurable: true
// });
// Для найкращої підтримки переглядачів, використовуйте:
A[k] = mappedValue;
}
// г. Збільшити k на 1.
k++;
}
// 9. повернути A
return A;
};
}
</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('ES5.1', '#sec-15.4.4.19', 'Array.prototype.map')}}</td>
<td>{{Spec2('ES5.1')}}</td>
<td>
<p>Початкове визначення. Реалізоване в JavaScript 1.6.</p>
</td>
</tr>
<tr>
<td>{{SpecName('ES6', '#sec-array.prototype.map', 'Array.prototype.map')}}</td>
<td>{{Spec2('ES6')}}</td>
<td></td>
</tr>
<tr>
<td>{{SpecName('ESDraft', '#sec-array.prototype.map', 'Array.prototype.map')}}</td>
<td>{{Spec2('ESDraft')}}</td>
<td></td>
</tr>
</tbody>
</table>
<h2 id="Сумісність_з_веб-переглядачами">Сумісність з веб-переглядачами</h2>
<div class="hidden">
<p>The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p>
</div>
<p>{{Compat("javascript.builtins.Array.map")}}</p>
<h2 id="Дивіться_також">Дивіться також</h2>
<ul>
<li>{{jsxref("Array.prototype.forEach()")}}</li>
<li>Об'єкт {{jsxref("Map")}}</li>
<li>{{jsxref("Array.from()")}}</li>
</ul>
|