.map()

Время чтения: меньше 5 мин

Кратко

Секция статьи "Кратко"

Метод map позволяет трансформировать один массив в другой при помощи функций-колбэка. Переданная функция будет вызвана для каждого элемента массива по порядку. Из результатов вызова функции будет собран новый массив.

Пример

Секция статьи "Пример"

Создадим массив квадратов:

        
          
          const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9]const squares = nums.map(function (num) {  return num * num})
          const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9]

const squares = nums.map(function (num) {
  return num * num
})

        
        
          
        
      

Результат: [1, 4, 9, 16, 25, 36, 49, 64, 81].

Либо можно сделать массив с объектами:

        
          
          const objects = nums.map(function (num) {  return {    field: num,  }})
          const objects = nums.map(function (num) {
  return {
    field: num,
  }
})

        
        
          
        
      

Результат: [ { field: 1 }, { field: 2 }, ... { field: 9 } ].

Интерактивный пример:

Открыть демо в новой вкладке

Как пишется

Секция статьи "Как пишется"

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

Функция, которую мы передаём в метод map, может принимать три параметра:

  • item — элемент массива в текущей итерации;
  • index — индекс текущего элемента;
  • arr — сам массив, который мы перебираем.

Суммируем числа, индексы и длины массива:

        
          
          const nums = [0, 1, 2, 3]const transformed = nums.map(function (num, index, arr) {  return num + index + arr.length})
          const nums = [0, 1, 2, 3]

const transformed = nums.map(function (num, index, arr) {
  return num + index + arr.length
})

        
        
          
        
      

Результат: [4, 6, 8, 10].

Как это понять

Секция статьи "Как это понять"

Часто возникают ситуации, когда на основе одного массива нужно создать другой массив, как-нибудь трансформировав исходные значения. Это можно сделать, используя обычные циклы for или while:

        
          
          const nums = [1, 2, 3, 4, 5]const transformed = []for (let i = 0; i < nums.length; i++) {  const num = nums[i]  const item = `${i}-${num}`  transformed.push(item)}console.log(transformed)// ['0-1', '1-2', '2-3', '3-4', '4-5']
          const nums = [1, 2, 3, 4, 5]

const transformed = []

for (let i = 0; i < nums.length; i++) {
  const num = nums[i]
  const item = `${i}-${num}`
  transformed.push(item)
}

console.log(transformed)
// ['0-1', '1-2', '2-3', '3-4', '4-5']

        
        
          
        
      

Задача решена, однако, как и другие встроенные методы массива, map позволяет написать код короче и проще для понимания:

        
          
          const nums = [1, 2, 3, 4, 5]const transformed = nums.map(function (num, i) {  return `${i}-${num}`})
          const nums = [1, 2, 3, 4, 5]

const transformed = nums.map(function (num, i) {
  return `${i}-${num}`
})

        
        
          
        
      

Результат тот же, но способ короче и проще.

Подсказки

Секция статьи "Подсказки"

💡 map возвращает новый массив, при этом исходный массив никак не изменится.

💡 При работе с map необходимо возвращать значение из функции-колбэка. Если не вернуть значение — например, забыв обработать какую-то ветку условия, то в итоговом массиве будет undefined:

        
          
          const nums = [1, 2, 3, 4, 5]const transformed = nums.map(function (num) {  if (num <= 3) {    return "less"  }  // Забыли обработать эту ветку условия})// ['less', 'less', 'less', undefined, undefined]
          const nums = [1, 2, 3, 4, 5]

const transformed = nums.map(function (num) {
  if (num <= 3) {
    return "less"
  }
  // Забыли обработать эту ветку условия
})
// ['less', 'less', 'less', undefined, undefined]

        
        
          
        
      

Передача контекста в колбэк-функцию

Секция статьи "Передача контекста в колбэк-функцию"

Вторым аргументом map может принимать значение, которое будет передано как контекст выполнения функции-колбэка:

        
          
          const nums = [1, 2, 3]const otherData = { delta: 5 }const transformed = nums.map(function (num) {  // this теперь ссылается на объект otherData  return num + this.delta}, otherData)console.log(transformed)// [ 6, 7, 8 ]
          const nums = [1, 2, 3]

const otherData = { delta: 5 }

const transformed = nums.map(function (num) {
  // this теперь ссылается на объект otherData
  return num + this.delta
}, otherData)

console.log(transformed)
// [ 6, 7, 8 ]

        
        
          
        
      

Обратите внимание, что стрелочным функциям нельзя изменить контекст выполнения, поэтому передача второго аргумента ни на что не повлияет:

        
          
          const nums = [1, 2, 3]const otherData = { delta: 5 }const transformed = nums.map((num) => {  // this.delta в данном случае равен undefined  return num + this.delta}, otherData)console.log(transformed)// [ NaN, NaN, NaN ]
          const nums = [1, 2, 3]

const otherData = { delta: 5 }

const transformed = nums.map((num) => {
  // this.delta в данном случае равен undefined
  return num + this.delta
}, otherData)

console.log(transformed)
// [ NaN, NaN, NaN ]

        
        
          
        
      

На практике

Секция статьи "На практике"

windrushfarer

Секция статьи "windrushfarer"

🛠 При работе с React или другой похожей на неё библиотекой map — это самый распространённый способ трансформировать массив данных в компоненты, которые в итоге будут на странице:

        
          
          function SomeComponent() {  const items = ['This', 'is', 'map!']  return (    <div>      {items.map(item => <span>{item}</span>)}    </div>  )}
          function SomeComponent() {

  const items = ['This', 'is', 'map!']

  return (
    <div>
      {items.map(item => <span>{item}</span>)}
    </div>
  )
}

        
        
          
        
      

🛠 Так как map возвращает массив, то у полученного массива мы можем продолжать по цепочке вызывать другие методы массива, в том числе, новый map, продолжая трансформацию новых данных:

        
          
          const nums = [1, 2, 3, 4, 5]const result = nums.map(...).filter(...).map(...)
          const nums = [1, 2, 3, 4, 5]

const result = nums.map(...).filter(...).map(...)