Diferença entre foreach() e map() em Javascript

Javascript

JavaScript tem alguns métodos que nos ajudam a iterar através de Arrays. Os dois mais usados foreach() e map() em Javascript. Mas acredito que exista muita duvida entre esse dois métodos.

Porque ambos fazem uma iteração e produzem algo. Então, qual é a diferença?

foreach() e map() em Javascript: Definições

Vamos definir cada método, e onde cada um se enquadra, para tentarmos entender melhor o que podemos fazer com cada um:

O método do map() recebe uma função como parâmetro. Essa função é invocada para cada elemento do Array, e ao final o método retorna um array totalmente novo preenchido com os resultados da chamada da função fornecida.

const numbers = [5, 4, 3, 2, 1]
console.log(numbers.map(element => element * element)) //[ 25, 16, 9, 4, 1 ]

Isto significa que ele retorna um novo array que contém uma imagem de cada elemento do array. Ele sempre retornará o mesmo número de itens.

O método forEach() recebe uma função como argumento e a executa uma vez para cada elemento do Array. No entanto, ao invés de retornar um novo array como o método map(), ele retorna undefined.

const numbers = [5, 4, 3, 2, 1]
console.log(numbers.forEach(element => element * element)) //undefined

Retorno do método

Como você já pode perceber, uma das principais diferenças entre foreach() e map() em Javascript é o retorno de cada método.

O método forEach() retorna undefined map() retorna um novo array com os elementos transformados.

let numbers = [5, 4, 3, 2, 1]
console.log(numbers.map(element => element * element)) //[ 25, 16, 9, 4, 1 ]
console.log(numbers.forEach(element => element * element)) //undefined

Capacidade de encadear outros métodos

A segunda diferença entre esses métodos é o fato de que o map() é encadeável. Isto significa que você pode anexar reduce(), sort(), filter() e assim por diante após executar o método map() em um array.

Isso é algo que você não pode fazer com forEach() porque, como você pode adivinhar, ela retorna undefined.

let numbers = [5, 4, 3, 2, 1]
const newArrayMap = numbers.map(element => element * element).filter(x => x > 9);
console.log(newArrayMap); //[ 25, 16 ]
const newArrayForEach = numbers.forEach(element => element * element).filter(x => x > 9);
console.log(newArrayForEach) // Cannot read property 'filter' of undefined

Mutabilidade

Mutabilidade significa “Aptidão ou capacidade para sofrer mutações.” Para JavaScript essa palavra tem o mesmo significado.

Um objeto mutável é um objeto cujo estado pode ser modificado após a sua criação. Em relação à mutabilidade, como os métodos foreach() e map() em Javascript, se comportam?

Bem, de acordo com a documentação da MDN:

forEach() não modifica o array no qual é chamado. (No entanto, o método callback pode fazer isso).

map() não modifica o array no qual ele é chamado (embora o método callback, se invocado, possa fazer isso).

Essa talvez seja a explicação mais confusa que já li nos últimos meses. Vamos clarificar as coisas.

Quando o método map() é chamado, ele retorna um Array completamente novo e não altera o Array original ao qual ele foi chamado.

Já o método forEach(), não retorna nada (undefined). Ele simplesmente chama uma função fornecida em cada elemento do seu array. Esta chamada de retorno tem permissão para alterar o Array que foi chamado.

Perceba no exemplo abaixo que o método map() faz as transformações necessárias e retorna um novo Array. Para simular o mesmo efeito usando forEach() eu precisei alterar o valor original.

let numbers = [5, 4, 3, 2, 1]
const newArrayMap = numbers.map(element => element * element);
console.log(newArrayMap); //[ 25, 16, 9, 4, 1 ]
console.log(numbers); //[ 5, 4, 3, 2, 1 ]
const newArrayForEach = numbers.forEach(
   (element, index) =>
      numbers[index] = element * element
);
console.log(numbers) // [ 25, 16, 9, 4, 1 ]

Desempenho

Apesar de muitos sites declararem que o método map() é até 70% mais rápido do que o método forEach(). Não foi exatamente isso que encontrei no meus testes.

Na verdade, descobri o contrário. Testei diversos cenários, em nenhum caso o forEach teve performance inferior. Você pode conferir um dos testes aqui. Acredito que se o efeito colateral de alterar o Array original não for um problema, o método forEach() se encaixa muito bem na proposta de ser eficiente.

Conclusão

Qual é o melhor?

Isso depende do resultado que você quer obter.
forEach() pode ser preferível quando você não está tentando mudar os dados no seu array, mas em vez disso quer apenas fazer algo com eles – como salvá-los em um banco de dados ou apenas exibir os dados:

let names = ['Elon', 'Jeff', 'Mark'];
names.forEach((name) => {
    console.log(name);
});
// Elon
// Jeff
// Mark

E o método map() pode ser o mais indicado para alterar os dados pois ele retorna um novo Array com os dados. E como o retorno é um Array nós podemos tirar vantagem disso para encadear outros métodos como (  map()filter()reduce(), etc.).

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

Confira os outros tutorias sobre Javascript, e se inscreva na nossa newsletter pra receber novidades!

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

0 Comments