Spec-Zone.ru › JavaScript

Array.prototype.map()

Базовая поддержка Широко доступно

Эта функция хорошо зарекомендовала себя и работает на многих устройствах и версиях браузеров. Она доступна в браузерах с июля 2015 года.

Метод map() экземпляров Array создает новый массив, заполненный результатами вызова предоставленной функции для каждого элемента в вызывающем массиве.

Попробуйте

const array = [1, 4, 9, 16];

// Pass a function to map
const mapped = array.map((x) => x * 2);

console.log(mapped);
// Expected output: Array [2, 8, 18, 32]

Синтаксис

map(callbackFn)
map(callbackFn, thisArg)

Параметры

callbackFn
Функция, которую необходимо выполнить для каждого элемента массива. Её возвращаемое значение добавляется как отдельный элемент в новый массив. Функция вызывается со следующими аргументами:
element
Текущий элемент, обрабатываемый в массиве.
index
Индекс текущего элемента, обрабатываемого в массиве.
array
Массив, для которого был вызван map().
thisArg Необязательный
Значение, которое будет использоваться в качестве this при выполнении callbackFn. См. итеративные методы.

Возвращаемое значение

Новый массив, где каждый элемент является результатом выполнения функции обратного вызова.

Описание

Метод map() является итеративным методом. Он вызывает предоставленную функцию callbackFn один раз для каждого элемента массива и создает новый массив из результатов. Прочитайте раздел итеративные методы для получения дополнительной информации о том, как эти методы работают в целом.

callbackFn вызывается только для индексов массива, которым присвоены значения. Он не вызывается для пустых слотов в разреженных массивах.

Метод map() является общим. Он ожидает, что значение this будет иметь свойство length и целочисленные свойства.

Поскольку map создает новый массив, вызов его без использования возвращаемого массива является антипаттерном; вместо этого используйте forEach или for...of.

Примеры

Преобразование массива чисел в массив квадратных корней

Следующий код берет массив чисел и создает новый массив, содержащий квадратные корни чисел из первого массива.

const numbers = [1, 4, 9];
const roots = numbers.map((num) => Math.sqrt(num));

// roots is now     [1, 2, 3]
// numbers is still [1, 4, 9]

Использование map для переформатирования объектов в массиве

Следующий код берет массив объектов и создает новый массив, содержащий переформатированные объекты.

const kvArray = [
  { key: 1, value: 10 },
  { key: 2, value: 20 },
  { key: 3, value: 30 },
];

const reformattedArray = kvArray.map(({ key, value }) => ({ [key]: value }));

console.log(reformattedArray); // [{ 1: 10 }, { 2: 20 }, { 3: 30 }]
console.log(kvArray);
// [
//   { key: 1, value: 10 },
//   { key: 2, value: 20 },
//   { key: 3, value: 30 }
// ]

Использование parseInt() с map()

Часто используется функция обратного вызова с одним аргументом (обрабатываемый элемент). Определенные функции также часто используются с одним аргументом, даже если они принимают дополнительные необязательные аргументы. Эти привычки могут привести к путанице. Рассмотрим:

["1", "2", "3"].map(parseInt);

Хотя можно было бы ожидать [1, 2, 3], фактическим результатом является [1, NaN, NaN].

parseInt часто используется с одним аргументом, но принимает два. Первый — это выражение, а второй — основание системы счисления. Функция обратного вызова Array.prototype.map передает 3 аргумента: элемент, индекс и массив. Третий аргумент игнорируется parseInt — но не второй! Это источник возможной путаницы.

Вот краткий пример шагов итерации:

/* 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

Чтобы решить эту проблему, определите другую функцию, которая принимает только один аргумент:

["1", "2", "3"].map((str) => parseInt(str, 10)); // [1, 2, 3]

Вы также можете использовать функцию Number, которая принимает только один аргумент:

["1", "2", "3"].map(Number); // [1, 2, 3]

// But unlike parseInt(), Number() will also return a float or (resolved) exponential notation:
["1.1", "2.2e2", "3e300"].map(Number); // [1.1, 220, 3e+300]

// For comparison, if we use parseInt() on the array above:
["1.1", "2.2e2", "3e300"].map((str) => parseInt(str, 10)); // [1, 2, 3]

См. A JavaScript optional argument hazard Аллена Вирфс-Брока для дальнейшего обсуждения.

В результирующем массиве присутствуют undefined

Когда возвращается undefined или ничего, в результирующем массиве присутствуют undefined. Если вы хотите удалить элемент вместо этого, используйте цепочку метода filter() или метод flatMap() и верните пустой массив, чтобы обозначить удаление.

const numbers = [1, 2, 3, 4];
const filteredNumbers = numbers.map((num, index) => {
  if (index < 3) {
    return num;
  }
});

// index goes from 0, so the filteredNumbers are 1,2,3 and undefined.
// filteredNumbers is [1, 2, 3, undefined]
// numbers is still [1, 2, 3, 4]

Маппинг с побочными эффектами

Функция обратного вызова может иметь побочные эффекты.

const cart = [5, 15, 25];
let total = 0;
const withTax = cart.map((cost) => {
  total += cost;
  return cost * 1.2;
});
console.log(withTax); // [6, 18, 30]
console.log(total); // 45

Это не рекомендуется, так как методы копирования лучше использовать с чистыми функциями. В этом случае мы можем выбрать итерацию по массиву дважды.

const cart = [5, 15, 25];
const total = cart.reduce((acc, cost) => acc + cost, 0);
const withTax = cart.map((cost) => cost * 1.2);

Иногда этот шаблон доходит до крайности, и единственное, что делает map(), — это вызывает побочные эффекты.

const products = [
  { name: "sports car" },
  { name: "laptop" },
  { name: "phone" },
];

products.map((product) => {
  product.price = 100;
});

Как упоминалось ранее, это антипаттерн. Если вы не используете возвращаемое значение map(), вместо этого используйте forEach() или цикл for...of.

products.forEach((product) => {
  product.price = 100;
});

Или, если вы хотите создать новый массив вместо этого:

const productsWithPrice = products.map((product) => ({
  ...product,
  price: 100,
}));

Использование третьего аргумента callbackFn

Аргумент array полезен, если вы хотите получить доступ к другому элементу в массиве, особенно когда у вас нет существующей переменной, ссылающейся на массив. Следующий пример сначала использует filter() для извлечения положительных значений, а затем использует map() для создания нового массива, где каждый элемент является средним арифметическим своих соседей и самого себя.

const numbers = [3, -1, 1, 4, 1, 5, 9, 2, 6];
const averaged = numbers
  .filter((num) => num > 0)
  .map((num, idx, arr) => {
    // Without the arr argument, there's no way to easily access the
    // intermediate array without saving it to a variable.
    const prev = arr[idx - 1];
    const next = arr[idx + 1];
    let count = 1;
    let total = num;
    if (prev !== undefined) {
      count++;
      total += prev;
    }
    if (next !== undefined) {
      count++;
      total += next;
    }
    const average = total / count;
    // Keep two decimal places
    return Math.round(average * 100) / 100;
  });
console.log(averaged); // [2, 2.67, 2, 3.33, 5, 5.33, 5.67, 4]

Аргумент array — это не массив, который строится — нет способа получить доступ к строящемуся массиву из функции обратного вызова.

Использование map() на разреженных массивах

Разреженный массив остается разреженным после map(). Индексы пустых слотов остаются пустыми в результирующем массиве, и функция обратного вызова не будет вызываться для них.

console.log(
  [1, , 3].map((x, index) => {
    console.log(`Visit ${index}`);
    return x * 2;
  }),
);
// Visit 0
// Visit 2
// [2, empty, 6]

Вызов map() на не-массивных объектах

Метод map() считывает свойство length this, а затем обращается к каждому свойству, ключ которого является неотрицательным целым числом, меньшим length.

const arrayLike = {
  length: 3,
  0: 2,
  1: 3,
  2: 4,
  3: 5, // ignored by map() since length is 3
};
console.log(Array.prototype.map.call(arrayLike, (x) => x ** 2));
// [ 4, 9, 16 ]

Этот пример показывает, как итерировать по коллекции объектов, собранных querySelectorAll(), возвращая массив, содержащий значения всех выбранных option элементов. Поскольку querySelectorAll() возвращает NodeList, который является похожим на массив объектом без метода map(), мы используем Array.prototype.map.call(), передавая elems в качестве значения this и функцию обратного вызова в качестве второго аргумента.

const elems = document.querySelectorAll("select option:checked");
const values = Array.prototype.map.call(elems, ({ value }) => value);

Вы также можете использовать Array.from() для преобразования elems в массив, а затем получить доступ к методу map().

Спецификации

Спецификация
ECMAScript® 2027 Language Specification
# sec-array.prototype.map

Совместимость с браузерами

Настольные компьютеры Мобильные устройства Сервер
Chrome Edge Firefox Opera Safari Chrome Android Firefox for Android Opera Android Safari on iOS Samsung Internet WebView Android WebView on iOS Bun Deno Node.js
map
1
12
1.5
9.5
3
18
4
10.1
1
1.0
4.4
1
1.0.0
1.0
0.10.0

См. также

  • Polyfill Array.prototype.map в core-js
  • es-shims polyfill Array.prototype.map
  • Руководство по индексированным коллекциям
  • Array
  • Array.prototype.forEach()
  • Array.from()
  • TypedArray.prototype.map()
  • Map

© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API