--- 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 ---
Метод map()
створює новий масив з результатами виклику наданої функції на кожному елементі масиву, який викликав метод.
{{EmbedInteractiveExample("pages/js/array-map.html")}}
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 https://github.com/mdn/interactive-examples and send us a pull request."
var new_array = arr.map(function callback(currentValue[, index[, array]]) { // Повернути елемент нового масиву new_array }[, thisArg])
callback
currentValue
index
{{optional_inline}}array
{{optional_inline}}map
.thisArg
{{optional_inline}}this
при виконанні callback
.Новий масив, кожен елемент якого є результатом функції callback
.
Метод map
викликає передану callback-функцію
один раз для кожного елементу масиву, в заданому порядку, та створює новий масив з результатів. callback
викликаться тільки для індексів яким відповідають значення, включно з undefined. Функція не викликається для елеметів значення яких відсутні (мається на увазі, індекси які не були явно задані, які були видалені або яким не було присвоєне значення).
Остільки map
створює новий масив, викликати його, якщо ви не збираєтесь використовувати повернений масив, є антишаблоном; скористайтесь натомість forEach
або for-of
. Ознаки того, що вам не підходить метод map
: А) Ви не використовуєте масив, який він повертає, і/або Б) Ви не повертаєте значення у функції callback
.
callback
викликається з трьома аргументами: значення елемента, індекс елемента, та масив на якому операцію було викликано.
Якщо thisArg
параметр переданий в map
, він буде використовуватись як ключове слово this для callback-функції
. В іншому випадку, значення {{jsxref("undefined")}} буде використане як this
. Значення this, яке спостерігається в callback-функції, в кінцевому рахунку визначається згідно звичайних правил для визначення this, видимого з функції.
map
не змінює масив, на якому був викликаний (хоча callback
, якщо був викликаний, може змінити).
Діапазон елементів, які обробляє метод map, визначений до того як callback-функція буде визвана вперше. Елементи які будуть додані до масиву після виклику map, не будуть оброблені callback-функцією. Якщо існуючі в масиві елементи змінені або видалені, їхні значення при потраплянні в callback-функцію, будуть такими якими вони є на той час коли map обробляє їх. Елементи які були видалені до і після того як map був визваний, ігноруються.
Згідно з алгоритмом, визначеним у специфікації, якщо масив на якому було викликано map, розріджений, то масив на виході теж буде розрідженим, залишаючи ті ж самі індекси пустими.
Наступний код бере масив з числами і створює новий масив, який складається з квадратних коренів чисел з першого масиву.
var numbers = [1, 4, 9]; var roots = numbers.map(function(num) { return Math.sqrt(num) }); // roots тепер [1, 2, 3] // numbers залишається [1, 4, 9]
Наступний код використовує масив з об'єктами щоб створити новий масив з переформатованими об'єктами.
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}]
Наступний код показує як map працює коли функція що потребує один аргумент, використовує його. Аргумент буде автоматично присвоєний з кожного елементу масиву коли map буде проходитись по оригінальному масиву..
var numbers = [1, 4, 9]; var doubles = numbers.map(function(num) { return num * 2; }); // doubles тепер [2, 8, 18] // numbers залишається [1, 4, 9]
map
Цей приклад показує як використовувати map на рядках ({{jsxref("String")}}) щоб отримати масив байтів в ASCII кодуванні яке відображає значення літер:
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]
map
з querySelectorAll
Даний приклад показує, як виконати перебір набору об'єктів, отриманих методом querySelectorAll
. Тому що метод querySelectorAll
повертає NodeList, який є колекцією об'єктів.
У даному випадку ми повертаємо значення всіх вибраних опцій на екрані:
var elems = document.querySelectorAll('select option:checked'); var values = Array.prototype.map.call(elems, function(obj) { return obj.value; });
Це простіше зробити методом {{jsxref("Array.from()")}}.
Загальноприйнято використовувати функцію callback з одним аргументом (елемент по якому проходиться функція). Деякі функції також використовуються з одним аргументом, хоча можуть приймати і більше додаткових аргументів, що не є обов'язковими. Це може призводити до неочікуваної поведінки.
Розглянемо:
["1", "2", "3"].map(parseInt);
Хоча можна було б очікувати [1, 2, 3]
, справжнім результатом буде [1, NaN, NaN]
.
Метод parseInt
часто використовується з одним аргументом, але приймає два. Перший - це вираз, а другий - основа системи числення для функції зворотного виклику. Array.prototype.map
передає 3 аргументи:
Третій аргумент ігнорується методом parseInt, але не другий, звідси й можлива плутанина. Ось стислий огляд кроків перебору:
// 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
Поговоримо про рішення.
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]
Ще один варіант результату метода map, що викликається з parseInt в якості параметра, виглядає наступним чином:
var xs = ['10', '10', '10']; xs = xs.map(parseInt); console.log(xs); // Результат 10,NaN,2 може бути неочікуваним, з огляду вищеописане.
Коли повертається undefined або нічого не повертається:
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]
Метод map
був доданий до ECMA-262 стандарту в 5-тій редакції; тому він може бути присутнім не у всіх реалізаціях стандарту. Ви можете обійти це, вставляючи наступний код на початок вашого скритпу, дозволяючи використовувати map в реалізаціях які ще його не підтримують. Цей алгоритм є точно таким який вказаний в ECMA-262, 5му виданні, передбачаючи що {{jsxref("Object")}}, {{jsxref("TypeError")}}, і {{jsxref("Array")}} мають свої власні значення і що callback.call
обчислює початкове значення {{jsxref("Function.prototype.call")}}
.
// Функціональні кроки 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; }; }
Специфікація | Статус | Коментар |
---|---|---|
{{SpecName('ES5.1', '#sec-15.4.4.19', 'Array.prototype.map')}} | {{Spec2('ES5.1')}} |
Початкове визначення. Реалізоване в JavaScript 1.6. |
{{SpecName('ES6', '#sec-array.prototype.map', 'Array.prototype.map')}} | {{Spec2('ES6')}} | |
{{SpecName('ESDraft', '#sec-array.prototype.map', 'Array.prototype.map')}} | {{Spec2('ESDraft')}} |
The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out https://github.com/mdn/browser-compat-data and send us a pull request.
{{Compat("javascript.builtins.Array.map")}}