He visto muchas preguntas que sugieren usar:
for (var i = 0; i < myArray.length; i++){ /* ... */ }
en vez de:
for (var i in myArray){ /* ... */ }
para matrices, debido a iteraciones inconsistentes ( ver aquí ).
Sin embargo, parece que no puedo encontrar nada que parezca preferir el bucle orientado a objetos:
myArray.forEach(function(item, index){ /* ... */ });
Lo que me parece mucho más intuitivo.
Para mi proyecto actual, la compatibilidad con IE8 es importante y estoy considerando usar el polyfill de Mozilla , sin embargo, no estoy 100% seguro de cómo funcionará.
- ¿Existen diferencias entre el bucle for estándar (el primer ejemplo anterior) y la implementación Array.prototype.forEach de los navegadores modernos?
- ¿Existe alguna diferencia entre las implementaciones de navegadores modernos y la implementación de Mozilla vinculada anteriormente (con especial atención a IE8)?
- El rendimiento no es un problema, solo la coherencia con las propiedades que se repiten.
javascript
arrays
for-loop
internet-explorer-8
iterator
Michael Lewis
fuente
fuente

breaksalirforEach. Pero una gran ventaja es crear un nuevo alcance con la función. Con el polyfill no deberías tener ningún problema (al menos no he encontrado ninguno).holesdondeundefineddebería estar y otros métodos rotos, comosliceyhasOwnPropertywrt para objetos DOM tipo matriz. Mis pruebas yes5 shimhan demostrado que dichos métodos con calce cumplen con la especificación (no se probó el calzo de MDN).forbucle, para eso essome.Array.find()para salir del bucle después de encontrar una primera coincidencia.Respuestas:
La diferencia más sustancial entre el
forbucle y elforEachmétodo es que, con el primero, puedebreaksalir del bucle. Puede simularcontinuesimplemente regresando de la función pasada aforEach, pero no hay forma de detener el bucle por completo.Aparte de eso, los dos logran efectivamente la misma funcionalidad. Otra diferencia menor involucra el alcance del índice (y todas las variables que lo contienen) en el ciclo for, debido a la elevación de variables.
// 'i' is scoped to the containing function for (var i = 0; i < arr.length; i++) { ... } // 'i' is scoped to the internal function arr.forEach(function (el, i) { ... });Sin embargo, encuentro que
forEaches mucho más expresivo: representa su intención de iterar a través de cada elemento de una matriz y le proporciona una referencia al elemento, no solo al índice. En general, todo se reduce al gusto personal, pero si puede usarloforEach, le recomendaría usarlo.Hay algunas diferencias más sustanciales entre las dos versiones, específicamente con respecto al rendimiento. De hecho, el bucle for simple funciona considerablemente mejor que el
forEachmétodo, como lo demuestra esta prueba jsperf .Si tal actuación es necesaria o no para usted, depende de usted decidir y, en la mayoría de los casos, preferiría la expresividad a la velocidad. Esta diferencia de velocidad probablemente se deba a las diferencias semánticas menores entre el bucle básico y el método cuando se opera en matrices dispersas, como se indica en esta respuesta .
Si no necesita el comportamiento de
forEachy / o necesita salir del ciclo temprano, puede usar Lo-Dash_.eachcomo alternativa, que también funcionará en todos los navegadores. Si está utilizando jQuery, también proporciona un similar$.each, solo tenga en cuenta las diferencias en los argumentos pasados a la función de devolución de llamada en cada variación.(En cuanto al
forEachpolyfill, debería funcionar en navegadores más antiguos sin problemas, si elige seguir esa ruta).fuente
eachno se comportan de la misma manera que la especificación ECMA5 deforEach, tienden a tratar todas las matrices como densas (para evitar errores de IE, siempre que lo sepa). De lo contrario, puede ser un "gotcha". Como referencia github.com/es-shims/es5-shim/issues/190Array.prototype.someque se repetirá hasta que devuelva un valor verdadero o hasta que haya recorrido completamente la matriz.Array.prototype.everyes similar a,Array.prototype.somepero se detiene si devuelve un valor falso.Array.prototype.forEachcon alguna versión no compatible tendría el potencial de romper tantas bibliotecas que evitarlo por esa razón no ayudaría, de todos modos.Puede usar su función foreach personalizada, que funcionará mucho mejor que Array.forEach
Debería agregar esto una vez a su código. Esto agregará una nueva función a la matriz.
function foreach(fn) { var arr = this; var len = arr.length; for(var i=0; i<len; ++i) { fn(arr[i], i); } } Object.defineProperty(Array.prototype, 'customForEach', { enumerable: false, value: foreach });Entonces puede usarlo en cualquier lugar como Array.forEach
[1,2,3].customForEach(function(val, i){ });La única diferencia es que es 3 veces más rápido. https://jsperf.com/native-arr-foreach-vs-custom-foreach
ACTUALIZACIÓN: En la nueva versión de Chrome, se mejoró el rendimiento de .forEach (). Sin embargo, la solución puede ofrecer un rendimiento adicional en otros navegadores.
fuente
Muchos desarrolladores (por ejemplo, Kyle Simpson) sugieren usarlo
.forEachpara indicar que la matriz tendrá un efecto secundario y.mappara funciones puras.forLos bucles se adaptan bien como una solución de propósito general para un número conocido de bucles o cualquier otro caso que no encaja, ya que es más fácil de comunicarse debido a su amplio soporte en la mayoría de los lenguajes de programación.p.ej
/* For Loop known number of iterations */ const numberOfSeasons = 4; for (let i = 0; i < numberOfSeasons; i++) { //Do Something } /* Pure transformation */ const arrayToBeUppercased = ['www', 'html', 'js', 'us']; const acronyms = arrayToBeUppercased.map((el) => el.toUpperCase)); /* Impure, side-effects with .forEach */ const acronymsHolder = []; ['www', 'html', 'js', 'us'].forEach((el) => acronymsHolder.push(el.toUpperCase()));En cuanto a las convenciones, esto parece lo mejor, sin embargo, la comunidad realmente no se ha conformado con una convención sobre los
for inbucles de protocolo de iteración más nuevos . En general, creo que es una buena idea seguir los conceptos de FP que la comunidad de JS parece estar abierta a adoptar.fuente