Eficiência do Javascript: 'for' vs 'forEach' [fechado]

103

Qual é o padrão atual em 2017 em Javascript com for () loops versus um .forEach.

Eu estou trabalhando atualmente o meu caminho através Colt Steeles "Web Dev Bootcamp" na Udemy e ele favorece forEachmais forem seus ensinamentos. No entanto, procurei várias coisas durante os exercícios como parte do trabalho do curso e encontro cada vez mais recomendações para usar um for-loop em vez de forEach. A maioria das pessoas parece afirmar que o loop for é mais eficiente.

É algo que mudou desde que o curso foi escrito (por volta de 2015) ou são realmente os prós e contras de cada um, que se aprenderá com mais experiência.

Qualquer conselho seria muito apreciado.

tonyrobbins
fonte
11
Por que se amarrar à ideia subjetiva de alguém de um padrão 2017? Adote um padrão atemporal, como escrever um código limpo e sustentável, sabendo que os engenheiros estão trabalhando duro para tornar as construções mais comumente usadas muito eficientes e, em seguida, otimizando o desempenho quando você tiver um problema de desempenho específico
2
Um nativo foré difícil de vencer por pura velocidade. forEach()invoca um callback para cada iteração; então, isso obviamente carrega consigo alguma sobrecarga.
cânone
1
sendo um desenvolvedor que dificilmente uso para ou foreach, a maior parte do trabalho é feito por métodos de mapear, filtrar ou reduzir.
EM
12
@AT, contanto que você não seja um daqueles caras que usa mapapenas para iteração e descarta o novo array que gera. Não sei quantas pessoas tive que corrigir nessa escolha de função específica somente neste site.
cânone
1
@canon concorda, a seleção do loop é importante e deve-se manter a produção e os resíduos de tais métodos em mente durante a escolha. Acredito que, para facilitar a leitura, "for loops" devem ser evitados.
EM

Respostas:

200

para

foros loops são muito mais eficientes. É uma construção de loop projetada especificamente para iterar enquanto uma condição for verdadeira , ao mesmo tempo que oferece um mecanismo de revisão (geralmente para aumentar o iterador). Exemplo:

for (var i=0, n=arr.length; i < n; ++i ) {
   ...
}

Isso não quer dizer que o for -loops será sempre mais eficiente, apenas que os mecanismos e navegadores JS os otimizaram para ser assim. Ao longo dos anos, houve compromissos quanto a qual construção de loop é mais eficiente (para, enquanto, reduz, inverte enquanto, etc) - diferentes navegadores e mecanismos JS têm suas próprias implementações que oferecem diferentes metodologias para produzir os mesmos resultados. À medida que os navegadores otimizam ainda mais para atender às demandas de desempenho, teoricamente [].forEachpoderiam ser implementados de forma mais rápida ou comparável a um for.

Benefícios:

  • eficiente
  • rescisão antecipada do loop (honras breake continue)
  • controle de condição ( i<npode ser qualquer coisa e não limitado ao tamanho de uma matriz)
  • escopo variável ( var ideixa idisponível após o término do loop)

para cada

.forEachsão métodos que iteram principalmente em arrays (também em outros enumeráveis, como objetos Mape Set). Eles são mais novos e fornecem um código subjetivamente mais fácil de ler. Exemplo:

[].forEach((val, index)=>{
   ...
});

Benefícios:

  • não envolve configuração de variável (itera sobre cada elemento da matriz)
  • funções / funções de seta abrangem a variável para o bloco
    No exemplo acima, valseria um parâmetro da função recém-criada. Portanto, quaisquer variáveis ​​chamadas valantes do loop manteriam seus valores após seu término.
  • subjetivamente mais sustentável, pois pode ser mais fácil identificar o que o código está fazendo - iterando sobre um enumerável; enquanto um loop for pode ser usado para qualquer número de esquemas de looping

atuação

Desempenho é um tópico complicado, que geralmente requer alguma experiência quando se trata de premeditação ou abordagem. Para determinar com antecedência (durante o desenvolvimento) quanta otimização pode ser necessária, um programador deve ter uma boa ideia da experiência anterior com a pasta de problemas, bem como um bom entendimento das soluções potenciais.

Usar o jQuery em alguns casos pode ser muito lento às vezes (um desenvolvedor experiente pode saber disso), enquanto outras vezes pode não ser um problema, caso em que a compatibilidade do navegador cruzado da biblioteca e a facilidade de executar outras funções (por exemplo, AJAX, tratamento de eventos) valeria a pena o tempo de desenvolvimento (e manutenção) economizado.

Outro exemplo é, se desempenho e otimização fossem tudo, não haveria outro código além de máquina ou montagem. Obviamente esse não é o caso, pois há muitas linguagens de alto e baixo nível diferentes, cada uma com suas próprias compensações. Essas compensações incluem, mas não estão limitadas a especialização, facilidade e velocidade de desenvolvimento, facilidade e velocidade de manutenção, código otimizado, código livre de erros, etc.

Abordagem

Se você não tem um bom entendimento se algo exigirá código otimizado, geralmente é uma boa regra escrever código sustentável primeiro. A partir daí, você pode testar e identificar o que precisa de mais atenção quando necessário.

Dito isso, certas otimizações óbvias devem fazer parte da prática geral e não exigir qualquer reflexão. Por exemplo, considere o seguinte loop:

for (var i=0; i < arr.length; ++i ){}

Para cada iteração do loop, JavaScript está recuperando as arr.lengthoperações de custo de pesquisa de chave em cada ciclo. Não há razão para que não seja:

for (var i=0, n=arr.length; i < n; ++i){}

Isso faz a mesma coisa, mas recupera apenas arr.lengthuma vez, armazenando a variável em cache e otimizando seu código.

Vol7ron
fonte
25
Resposta excelente, completa e não presunçosa, não limitada a um único ponto no tempo, implementação ou teste de micro-benchmark.
1
Perfeito, isso é exatamente o que eu estava procurando e dá muito mais profundidade do que o vídeo poderia. Eu realmente aprecio isso, ser novo há muito a aprender e essas são as coisas que são fáceis de ignorar, apenas favorecendo um em detrimento do outro sem nenhum motivo que possa atrapalhar você no futuro. Muito Obrigado!
tonyrobbins
2
O for-loop geralmente tem uma vantagem em termos de depuração: eles são fáceis de entrar, fazer um breakpoint e inspecionar. Com forEach (), o nível de retorno de chamada extra pode complicar um pouco as coisas.
Eric Grange,
1
@FelipeBuccioni obrigado, na verdade eu ia dar uma olhada nisso, pois acho que os motores agora verificam se um array sofreria mutação para determinar se o comprimento está em cache. Porém, para fins de legado, acho que os mecanismos de otimização não eram tão generosos e o comprimento era um impacto no desempenho de cada iteração. Vou dar uma olhada em seu artigo e incorporá-lo à resposta quando tiver tempo, ou espero que um membro notável da comunidade faça uma emenda como uma edição para mim :)
vol7ron
6
Gostei muito da explicação desta resposta e da frase [...], if performance and optimization was everything, there would be no other code than machine or assembly.. Acredito que com a letinstrução para declarar uma variável local de escopo de bloco, o segundo benefício de forEachnão é mais uma vantagem sobre o forloop, a menos que em um ambiente sem suporte para let.
user7393973