dr.Brain

doctor Brain

мир глазами веб-разработчика

JavaScript: foreach и map

различия методов forEach и map, о которых должен знать каждый разработчик

dr.Brain

время чтения 3 мин.

Photo by Paul Bergmeir on Unsplash

Для перебора элементов массива в JavaScript есть несколько удобных методов. Из них наиболее популярны Array.prototype.map() и Array.prototype.forEach(). Для начинающих программистов в использовании этих методов есть несколько неочевидных моментов: ведь, оба метода предназначены для перебора элементов и оба возвращают какой-то результат. Так в чем же различия?


Содержание


Определения

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

То есть, этот метод возвращает новый массив, содержащий образы всех элементов массива.

const myAwesomeArray = [5, 4, 3, 2, 1]
myAwesomeArray.map(x => x * x)

// Результат: [25, 16, 9, 4, 1]

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

const myAwesomeArray = [
  { id: 1, name: "John" },
  { id: 2, name: "Ali" },
  { id: 3, name: "Mass" },
]

myAwesomeArray.forEach(element => console.log(element.name))
// Результат:
// John
// Ali
// Mass

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

Возвращаемое значение - основное различие между map и forEach: forEach возвращает undefined, в то время как map возвращает новый массив с измененными элементами. Даже, если оба метода выполняют одну и ту же работу, возвращаемые значения будут разными.

const myAwesomeArray = [1, 2, 3, 4, 5]
myAwesomeArray.forEach(x => x * x)
// Возвращаемое значение: undefined

myAwesomeArray.map(x => x * x)
// Возвращаемое значение: [1, 4, 9, 16, 25]

Связывание методов

Другим важным различием этих методов является то, что map можно связывать с другими методами. Это означает, что Вы можете присоединить методы reduce(), sort(), filter() после применения к массиву метода map().

Вы не сможете проделать то же самое с forEach() только потому, что, как мы уже знаем, этот метод возвращает undefined.

const myAwesomeArray = [1, 2, 3, 4, 5]
myAwesomeArray.forEach(x => x * x).reduce((total, value) => total + value)
// Uncaught TypeError: Cannot read property 'reduce' of undefined

myAwesomeArray.map(x => x * x).reduce((total, value) => total + value)
// Возвращает значение: 55

Изменяемость

Изменяемый (мутирующий) объект - объект, состояние которого модифицируется после его создания. Попробуем разобраться: какое отношение к изменяемости имеют методы map и forEach.

Если опираться на информацию из документации MDN, оба метода не изменяют массивы (хотя, при вызове callback-функции это происходит).

Мы знаем, что и map, и forEach получают callback-функцию в качестве аргумента. Так, какой же из методов не приводит к изменению массива?

Вспомним, как работает каждый из методов. map возвращает совершенно новый измененный массив, в то время как forEach, возвращая undefined, при определенных условиях изменяет исходный массив с помощью callback-функции.

Именно поэтому map не ведет к мутированию исходного массива, в то время как forEach делает это.

Производительность

Измерение производительности показывает, что различия между map и forEach минимальны и зависят от множества факторов, в том числе от конфигурации компьютера, количества элементов и так далее.

Вы можете самостоятельно проверить производительность с помощью jsPerf и примера, приведенного ниже:

const myAwesomeArray = [1, 2, 3, 4, 5]

const startForEach = performance.now()
myAwesomeArray.forEach(x => (x + x) * 10000000000)
const endForEach = performance.now()
console.log(`Speed [forEach]: ${endForEach - startForEach} miliseconds`)

const startMap = performance.now()
myAwesomeArray.map(x => (x + x) * 10000000000)
const endMap = performance.now()
console.log(`Speed [map]: ${endMap - startMap} miliseconds`)

Заключение

Выбор между map и forEach, как всегда, будет зависеть от конкретного случая.

Если Вы планируете изменять новые данные - выбирайте map.

В случае, если нужно модифицировать элементы исходного массива, подойдет forEach.


Спасибо за внимание.

Новые публикации

Далее

Категории

О нас

Frontend & Backend. Статьи, обзоры, заметки, код, уроки.