Lab / JavaScript

JavaScript: В чем разница между Map и ForEach?

Если вы работали с JavaScript, вероятно, вам приходилось сталкиватся с двумя, казалось бы, похожими фуннкциями: Array.prototype.map() и Array.prototype.forEach(). Давайте разберёмся в чём-же разница?

Этой статьёй я открываю мини курс по работе с данными в JavaScript:

На портале для разработчиков "MDN" есть вот такое определение:

forEach() —  выполняет указанную функцию для каждого элемента массива.

map()  — создаёт новый массив с результатом вызова указанной функции для каждого элемента массива.

Что именно это означает?

Функция forEach() фактически ничего не возвращает (undefined). Она просто вызывает указанную функцию для каждого элемента вашего массива. Этот каллбек разрешает мутировать вызывающий массив.

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

Примеры кода

Рассмотрим на примере массива чисел.

let arr = [1, 2, 3, 4, 5];

Если бы мы хотели умножить на два каждый элемент массива, попробуем сделать это при помощи, forEach() и затем map().

Обратите внмание — вы никогда не сможете получить return из функции forEach значения просто отбрасываются.

arr.forEach((num, index) => {
    return arr[index] = num * 2;
});

// Результат
// arr = [2, 4, 6, 8, 10]

Аналогичный пример с помощью функции map

let doubled = arr.map(num => {
    return num * 2;
});

// Результат
// doubled = [2, 4, 6, 8, 10]

Есть ли разница в скорости выполнения?

jsPerf — отличный сайт для тестирования скорости различных методов и функций в JavasScript.

Давайте мосмотрим на мой результат тестирования:

Как вы можете видеть, на моём компьютере функция forEach () выполнился на 82% медленнее, чем map(). Возможно, ваш браузер выдаст иной результат, но в целом тенденция понятна.

Функция map() может оказаться для вас более удобной и понятной если вы предпочитаете функциональный стиль программирования на JS. Дело в том что foreach() модифицирует оригинальный массив тогда как map() возвращает совершенно новый массив, оставляя исходный неизменным.

Так что же выбрать?

Выбор как обычно зависит от решаемой вами задачи.

forEach() может быть предпочтительнее, если вы не пытаетесь изменить данные в своем массиве, вместо этого хотите просто что-то сделать с ним — например, сохранить его в базе данных или вывести в консоль:

let arr = ['a', 'b', 'c', 'd'];
arr.forEach((letter) => {
    console.log(letter);
});
// a
// b
// c
// d

В то время как map() может быть предпочтительнее при изменении данных. Он не только быстрее, но и возвращает новый массив. Он не только быстрее, но и возвращает новый массив. Это означает, что мы можем использовать другие классные функции, такие как: map()filter()reduce() и прочие.

let arr = [1, 2, 3, 4, 5];
let arr2 = arr.map(num => num * 2).filter(num => num > 5);
// arr2 = [6, 8, 10]

Что мы тут сделали? Перемножили каждый из элементов первого массива на два и затем отфильтровали массив через функцию filter(), оставив только те значения, что больше 5ти.

Если вы хотите узнать больше о маппинге, уменьшении и фильтрации, ознакомьтесь с этой статьёй https://codeburst.io/javascrip... возможно в будущем переведу её и выложу здесь.

Выводы:

Практически всё, что вы можете сделать при помощи функции  forEach(), можно с таким-же успехом реализовать с map() и наоборот.

Функция map() выделяет память и сохраняет возвращаемые значения. forEach() же в свою очередь отбрасывает возвращаемые значения и всегда возвращает undefined.

forEach() позволяет функции обратного вызова мутировать текущий массив.  В то время как map() вместо этого вернет новый массив.