Eficacia de JavaScript: 'for' vs 'forEach' [cerrado]

103

¿Cuál es el estándar actual en 2017 en Javascript con bucles for () frente a .forEach?

Actualmente estoy trabajando mi camino a través de Colt Steele "Web Dev Bootcamp" en Udemy y está a favor de forEachmás foren sus enseñanzas. Sin embargo, he buscado varias cosas durante los ejercicios como parte del trabajo del curso y encuentro más y más recomendaciones para usar un for-loop en lugar de forEach. La mayoría de la gente parece afirmar que el ciclo for es más eficiente.

¿Es esto algo que ha cambiado desde que se escribió el curso (alrededor de 2015) o son realmente los pros y los contras de cada uno, que se aprenderá con más experiencia?

Cualquier consejo será muy apreciado.

tonyrobbins
fuente
11
¿Por qué atarse a la idea subjetiva de alguien de un estándar de 2017? Adopción de una norma sin tiempo, como escribir código limpio y fácil de mantener, a sabiendas de que los ingenieros están trabajando duro para hacer las construcciones utilizadas más comúnmente muy eficiente, y luego optimizar el rendimiento cuando se tiene un problema de rendimiento específico
2
Un nativo fores difícil de superar por pura velocidad. forEach()invoca una devolución de llamada para cada iteración; por lo que obviamente lleva consigo algunos gastos generales.
canon
1
Siendo un desarrollador que apenas uso para o para cada uno, la mayor parte del trabajo se realiza mediante métodos de mapa, filtro o reducción.
EL
12
@AT siempre y cuando no sea uno de esos tipos que usa mapúnicamente para la iteración y descarta la nueva matriz que genera. No sé cuántas personas he tenido que corregir en esa opción de función en particular solo en este sitio.
canon
1
@canon estuvo de acuerdo, la selección de bucle es importante y uno debe tener en cuenta la salida y el residuo de tales métodos al elegir. Creo que por motivos de legibilidad se deben evitar los "bucles for" simples.
EL

Respuestas:

199

para

forlos bucles son mucho más eficientes. Es una construcción de bucle diseñada específicamente para iterar mientras una condición es verdadera , al mismo tiempo que ofrece un mecanismo de pasos (generalmente para aumentar el iterador). Ejemplo:

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

Esto no sugiere que los bucles for siempre serán más eficientes, solo que los motores y navegadores JS los han optimizado para serlo. A lo largo de los años, ha habido compromisos en cuanto a qué construcción de bucle es más eficiente (para, mientras, reducir, invertir-mientras, etc.): diferentes navegadores y motores JS tienen sus propias implementaciones que ofrecen diferentes metodologías para producir los mismos resultados. A medida que los navegadores se optimizan aún más para satisfacer las demandas de rendimiento, teóricamente se [].forEachpodría implementar de tal manera que sea más rápido o comparable a un for.

Beneficios:

  • eficiente
  • terminación anticipada del ciclo (honores breaky continue)
  • control de condición ( i<npuede ser cualquier cosa y no estar vinculado al tamaño de una matriz)
  • alcance variable ( var ideja idisponible después de que finaliza el ciclo)

para cada

.forEachson métodos que iteran principalmente sobre matrices (también sobre otros enumerables, como Mapy Setobjetos). Son más nuevos y proporcionan un código que es subjetivamente más fácil de leer. Ejemplo:

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

Beneficios:

  • no implica la configuración de variables (itera sobre cada elemento de la matriz)
  • functions / arrow-functions amplían la variable al bloque
    En el ejemplo anterior, valsería un parámetro de la función recién creada. Por lo tanto, cualquier variable llamada valantes del ciclo mantendría sus valores después de que finalice.
  • subjetivamente más mantenible, ya que puede ser más fácil identificar qué está haciendo el código: está iterando sobre un enumerable; mientras que un bucle for podría usarse para cualquier número de esquemas de bucle

Actuación

El rendimiento es un tema complicado, que generalmente requiere algo de experiencia cuando se trata de previsión o enfoque. Para determinar de antemano (durante el desarrollo) cuánta optimización puede ser necesaria, un programador debe tener una buena idea de la experiencia pasada con el caso del problema, así como una buena comprensión de las posibles soluciones.

El uso de jQuery en algunos casos puede ser demasiado lento a veces (un desarrollador experimentado puede saber eso), mientras que otras veces puede no ser un problema, en cuyo caso la compatibilidad de la biblioteca con el navegador cruzado y la facilidad para realizar otras funciones (por ejemplo, AJAX, manejo de eventos) valdría la pena el tiempo de desarrollo (y mantenimiento) ahorrado.

Otro ejemplo es, si el rendimiento y la optimización lo fueran todo, no habría otro código que máquina o ensamblaje. Obviamente, ese no es el caso, ya que hay muchos lenguajes diferentes de alto y bajo nivel, cada uno con sus propias compensaciones. Estas compensaciones incluyen, entre otras, especialización, facilidad y velocidad de desarrollo, facilidad y velocidad de mantenimiento, código optimizado, código libre de errores, etc.

Acercarse

Si no comprende bien si algo requerirá un código optimizado, generalmente es una buena regla general escribir primero código mantenible. A partir de ahí, puede probar e identificar qué necesita más atención cuando sea necesario.

Dicho esto, ciertas optimizaciones obvias deberían ser parte de la práctica general y no requieren ningún pensamiento. Por ejemplo, considere el siguiente ciclo:

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

Para cada iteración del ciclo, JavaScript recupera las arr.lengthoperaciones de costeo de búsqueda de claves en cada ciclo. No hay ninguna razón por la que esto no debería ser:

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

Esto hace lo mismo, pero solo se recupera arr.lengthuna vez, almacenando en caché la variable y optimizando su código.

vol7ron
fuente
25
Respuesta excelente, exhaustiva y no presuntuosa, que no se limita a un solo punto en el tiempo, implementación o prueba de micro-benchmark.
1
Perfecto, eso es exactamente lo que estaba buscando y da mucha más profundidad que el video. Realmente aprecio esto, siendo nuevo hay mucho que aprender y estas son las cosas que es fácil pasar por alto simplemente favoreciendo una sobre la otra sin ninguna razón que pueda obstaculizarlo en el futuro. ¡Muchas gracias!
Tonyrobbins
2
for-loop a menudo tiene una ventaja en términos de depuración: son trivila para entrar, interrumpir e inspeccionar. Con forEach (), el nivel de devolución de llamada adicional puede complicar un poco las cosas.
Eric Grange
1
@FelipeBuccioni gracias, en realidad iba a investigar eso, ya que creo que los motores ahora verifican si una matriz se mutaría para determinar si la longitud está almacenada en caché. Sin embargo, para propósitos heredados, creo que los motores de optimización no fueron tan generosos y la longitud fue un impacto en el rendimiento en cada iteración.
Revisaré
6
Realmente disfruto la explicación en esta respuesta y la frase [...], if performance and optimization was everything, there would be no other code than machine or assembly.. Creo que con la letdeclaración para declarar una variable local de alcance de bloque, el segundo beneficio de forEachya no es una ventaja sobre el forbucle a menos que esté en un entorno sin soporte para let.
user7393973