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

Попробуем прийти к этой функции через примеры. Возьмём список пользователей из предыдущего урока и извлечём из него имена всех пользователей.

const users = [
  { name: 'Igor', age: 19 },
  { name: 'Danil', age: 1 },
  { name: 'Vovan', age: 4 },
  { name: 'Matvey', age: 16 },
];

const result = [];
for ({ name } of users) {
  result.push(name);
}

console.log(result); // => ['Igor', 'Danil', 'Vovan', 'Matvey']

Здесь мы видим обычную агрегацию с использованием цикла for...of. А что, если нам понадобится извлечь возраст? Повторяем:

const users = [
  { name: 'Igor', age: 19 },
  { name: 'Danil', age: 1 },
  { name: 'Vovan', age: 4 },
  { name: 'Matvey', age: 16 },
];

const result = [];
for ({ age } of users) {
  result.push(age);
}

console.log(result); // => [19, 1, 4, 16]

В примерах выше легко увидеть закономерность. Выполняется один и тот же проход по циклу, и результат собирается в массив result. Единственное, что меняется — значение, которое мы извлекаем из элементов исходного массива. Именно этот паттерн называется "отображением".

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

const names = users.map((user) => user.name);
// вариант с дестракчерингом параметра:
// const names = users.map(({ name }) => name);

console.log(names); // => ['Igor', 'Danil', 'Vovan', 'Matvey']

//: # (FIXME: пример передачи "готовой" callback-функция, типа arr.map(Math.sqrt)) Метод map принимает первым параметром callback-функцию. Дальше внутри себя map перебирает элементы переданной коллекции и для каждого элемента вызывает callback-функцию. На вход этой функции передаётся элемент исходного массива, а её результат записывается в новый массив, который и возвращается наружу.

Некоторые замечания относительно метода map (они относятся в принципе к операции отображения):

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

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

const numbers = [5, 2, 3];

const newNumbers = numbers.map((number) => number ** 2);

console.log(newNumbers); // => [25, 4, 9]

Пример выглядит искусственно, но хорошо отражает суть операции.

Реализация

Напишем свою собственную функцию, реализующую операцию отображения:

const myMap = (callback, collection) => {
  const result = [];
  for (item of collection) {
    const newItem = callback(item);
    result.push(newItem);
  }

  return result;
}

Главное отличие кода функции myMap от ручного обхода массива заключается в том, что функция myMap не знает, что нужно сделать с каждым элементом массива. Поэтому она принимает первым аргументом функцию, которую вызывает для каждого элемента исходного массива, а результат вызова записывается в выходной массив. Чем будет этот результат — функция myMap не знает, и ей этого знать не нужно. Ответственность за обработку лежит на пользователях.


Дополнительные материалы

  1. Метод map
Мы учим программированию с нуля до стажировки и работы. Попробуйте наш бесплатный курс «Введение в программирование» или полные программы обучения по Node, PHP, Python и Java.

Хекслет

Подробнее о том, почему наше обучение работает →