¿For-each sobre un array en JavaScript?
¿Cómo puedo recorrer en bucle todas las entradas de una matriz utilizando JavaScript?
Pensé que era algo como esto:
forEach(instance in theArray)
Donde elArreglo
es mi matriz, pero esto parece ser incorrecto.
4427
3
TL;DR
for-in
a menos que lo utilices con salvaguardas o al menos seas consciente de por qué te puede picar.for-of
(sólo en ES2015+),Array#forEach
([spec
][1] | [MDN
][2]) (o sus parientessome
y similares) (sólo ES5+),for
a la antigua,o
for-in
con salvaguardas. Pero hay mucho más que explorar, sigue leyendo...JavaScript tiene una poderosa semántica para hacer bucles a través de arrays y objetos tipo array. He dividido la respuesta en dos partes: Opciones para arrays genuinos, y opciones para cosas que son sólo array-like, como el objeto
arguments
, otros objetos iterables (ES2015+), colecciones DOM, etc. Me gustaría señalar rápidamente que puedes utilizar las opciones de ES2015 ahora, incluso en motores ES5, transpilando ES2015 a ES5. Busca "ES2015 transpiling" / "ES6 transpiling" para saber más... Bien, veamos nuestras opciones:Para los Arrays reales
Tienes tres opciones en [ECMAScript 5][3] ("ES5"), la versión más ampliamente soportada en este momento, y dos más añadidas en [ECMAScript 2015][4] ("ES2015", "ES6"):
forEach
y afines (ES5+)for
.for-in
correctamentefor-of
(usar un iterador implícitamente) (ES2015+)1. Usar
forEach
y similaresEn cualquier entorno vagamente moderno (por tanto, no en IE8) donde tengas acceso a las características
Array
añadidas por ES5 (directamente o usando polyfills), puedes usarforEach
([spec
][1] | [MDN
][2]):forEach
acepta una función de callback y, opcionalmente, un valor para usar comothis
cuando se llama a ese callback (no se usa arriba). La llamada de retorno es llamada para cada entrada del array, en orden, saltando las entradas inexistentes en los arrays dispersos. Aunque arriba sólo he utilizado un argumento, la llamada de retorno se llama con tres: El valor de cada entrada, el índice de esa entrada y una referencia al array sobre el que se está iterando (en caso de que tu función no lo tenga ya a mano). A menos que estés soportando navegadores obsoletos como IE8 (que NetApps muestra en poco más del 4% de la cuota de mercado a partir de este escrito en septiembre de 2016), puedes utilizar felizmenteforEach
en una página web de propósito general sin un shim. Si necesitas soportar navegadores obsoletos, es fácil hacer un shimming/polyfilling deforEach
(busca "es5 shim" para varias opciones).forEach
tiene la ventaja de que no es necesario declarar las variables de indexación y de valor en el ámbito contenedor, ya que se suministran como argumentos a la función de iteración, y por lo tanto están bien delimitadas sólo para esa iteración. Si te preocupa el coste en tiempo de ejecución de hacer una llamada a la función para cada entrada del array, no lo hagas; detalles. Además,forEach
es la función de "bucle a través de todos ellos", pero ES5 definió varias otras funciones útiles para "trabajar a través del array y hacer cosas", incluyendo:every
][5] (detiene el bucle la primera vez que el callback devuelvefalse
o algo falso)some
][6] (detiene el bucle la primera vez que la llamada de retorno devuelvetrue
o algo verdadero)filter
][7] (crea un nuevo array incluyendo los elementos en los que la función de filtrado devuelvetrue
y omitiendo los que devuelvefalse
)map
][8] (crea un nuevo array a partir de los valores devueltos por la llamada de retorno)reduce
][9] (construye un valor llamando repetidamente a la llamada de retorno, pasando valores anteriores; ver la especificación para los detalles; útil para sumar el contenido de un array y muchas otras cosas)reduceRight
][10] (comoreduce
, pero funciona en orden descendente en lugar de ascendente)2. Utilice un simple bucle
for
.A veces las viejas formas son las mejores:
Si la longitud del array no va a cambiar durante el bucle, y está en un código sensible al rendimiento (poco probable), una versión un poco más complicada que agarre la longitud por adelantado podría ser un tiny poco más rápida:
Y/o contando hacia atrás:
Pero con los motores modernos de JavaScript, es raro que necesites sacarle ese último jugo. En ES2015 y superior, puedes hacer que tus variables de índice y valor sean locales al bucle
for
:Y cuando haces eso, no sólo
value
sino tambiénindex
se recrea para cada iteración del bucle, lo que significa que los cierres creados en el cuerpo del bucle mantienen una referencia alindex
(yvalue
) creado para esa iteración específica:Si tuvieras cinco divs, obtendrías "Index is: 0" si se hace clic en el primero y "El índice es: 4" si haces clic en el último. Esto no funciona si usas
var
en lugar delet
.3. Usa
for-in
correctamenteLa gente te dirá que uses
for-in
, pero [para eso no sirvefor-in
][11].for-in
recorre las propiedades enumerables de un objeto, no los índices de un array. El orden no está garantizado, ni siquiera en ES2015 (ES6). ES2015+ define un orden para las propiedades de los objetos (a través de[[OwnPropertyKeys]]
,[[Enumerate]]
, y cosas que las usan como [Object.getOwnPropertyKeys
][12]), pero no define quefor-in
seguirá ese orden. (Detalles en [esta otra respuesta][13].) Los únicos casos reales de uso defor-in
en un array son:for-in
para visitar esos elementos del array sparese si usas las salvaguardas adecuadas:**Nota: Esta respuesta está irremediablemente desfasada. Para un enfoque más moderno, mira los métodos disponibles en un array. Los métodos de interés podrían ser:
La forma estándar de iterar un array en JavaScript es un bucle vainilla
for
:Tenga en cuenta, sin embargo, que este enfoque sólo es bueno si usted tiene una matriz densa, y cada índice está ocupado por un elemento. Si el array es disperso, entonces puedes tener problemas de rendimiento con este enfoque, ya que iterarás sobre un montón de índices que realmente no existen en el array. En este caso, un bucle
for .. in
podría ser una mejor idea. **Sin embargo, debe utilizar las salvaguardias apropiadas para asegurarse de que sólo se actúa sobre las propiedades deseadas del array (es decir, los elementos del array), ya que el buclefor..in
también se enumerará en los navegadores antiguos, o si las propiedades adicionales se definen comoenumerables
.En ECMAScript 5 habrá un método forEach en el prototipo del array, pero no está soportado en los navegadores antiguos. Así que para poder usarlo de forma consistente debes tener un entorno que lo soporte (por ejemplo, Node.js para JavaScript del lado del servidor), o usar un "Polyfill". Sin embargo, el "Polyfill" para esta funcionalidad es trivial y, dado que facilita la lectura del código, es un buen "polyfill" a incluir.
Si quieres hacer un bucle sobre un array, utiliza el bucle estándar de tres partes
for
.Puedes obtener algunas optimizaciones de rendimiento almacenando en caché
miMatriz.longitud
o iterando sobre ella hacia atrás.