dante1986
¿Cómo puedo recorrer todas las entradas en una matriz usando JavaScript?
PatrikAkerstrand
Nota: Esta respuesta está irremediablemente desactualizada. Para un enfoque más moderno, mira los métodos disponibles en una matriz. Los métodos de interés pueden ser:
- para cada
- mapa
- filtrar
- Código Postal
- reducir
- cada
- alguno
La forma estándar de iterar una matriz en JavaScript es una vainilla for
-círculo:
var length = arr.length,
element = null;
for (var i = 0; i < length; i++) {
element = arr[i];
// Do something with element
}
Tenga en cuenta, sin embargo, que este enfoque solo es bueno si tiene una matriz densa y cada índice está ocupado por un elemento. Si la matriz es escasa, puede tener problemas de rendimiento con este enfoque, ya que iterará sobre muchos índices que no De Verdad existen en la matriz. En este caso, un for .. in
-loop podría ser una mejor idea. Sin embargodebe utilizar las medidas de seguridad adecuadas para garantizar que solo se actúe sobre las propiedades deseadas de la matriz (es decir, los elementos de la matriz), ya que el for..in
-loop también se enumerará en navegadores heredados, o si las propiedades adicionales se definen como enumerable
.
En ECMAScript 5 habrá un método forEach en el prototipo de matriz, pero no es compatible con navegadores heredados. Entonces, para poder usarlo de manera consistente, debe tener un entorno que lo admita (por ejemplo, Nodo.js para JavaScript del lado del servidor), o use un “Polyfill”. El Polyfill para esta funcionalidad es, sin embargo, trivial y dado que hace que el código sea más fácil de leer, es un buen polyfill para incluir.
-
¿Hay alguna manera de hacerlo en una sola línea de código? Por ejemplo en facebook me gusta acelerar los videos con
document.getElementsByTagName("video")[28].playbackRate = 2.2
. Si pudiera mapear fácilmente todos los elementos, podría evitar tener que identificar qué video (por ejemplo, el índice 28 en este caso). ¿Algunas ideas?– stevec
5 sep 2020 a las 19:39
-
@stevec: Array.from(document.querySelectorAll(‘video’)).forEach(video => video.playbackRate = 2.2);
– Patrik Akerstrand
14 de septiembre de 2020 a las 6:24
joeytwiddle
Bucle hacia atrás
Pienso que el reverso for loop merece una mención aquí:
for (var i = array.length; i--; ) {
// process array[i]
}
ventajas:
- No es necesario declarar un temporal
len
variable, o comparar conarray.length
en cada iteración, cualquiera de las cuales podría ser una optimización mínima. - Eliminación de hermanos del DOM en orden inverso suele ser más eficiente. (El navegador necesita cambiar menos elementos en sus matrices internas).
- Si usted modificar la matriz durante el bucle, en o después del índice i (por ejemplo, elimina o inserta un elemento en
array[i]
), entonces un bucle hacia adelante omitiría el elemento que se desplazó a la izquierda en la posición io volver a procesar el iel elemento que se desplazó a la derecha. En un bucle for tradicional, usted pudo actualizar i para apuntar al siguiente elemento que necesita procesamiento – 1, pero simplemente invertir la dirección de la iteración es a menudo una más simple y una solución más elegante. - Del mismo modo, al modificar o eliminar anidado Elementos DOM, procesamiento inverso puede eludir errores. Por ejemplo, considere modificar el código HTML interno de un nodo principal antes de manejar sus elementos secundarios. En el momento en que se alcance el nodo secundario, se separará del DOM y se reemplazará por un elemento secundario recién creado cuando se escribió el HTML interno del elemento primario.
- Está corto escribir, y leer, que algunas de las otras opciones disponibles. Aunque pierde con
forEach()
y a ES6for ... of
.
Desventajas:
- Procesa los artículos en orden inverso. Si estaba construyendo una nueva matriz a partir de los resultados, o imprimiendo cosas en la pantalla, naturalmente la salida se invertirá con respecto al pedido original.
- La inserción repetida de hermanos en el DOM como primer hijo para conservar su orden es menos eficiente. (El navegador seguiría teniendo que cambiar las cosas correctamente). Para crear nodos DOM de manera eficiente y en orden, simplemente avance y agregue como de costumbre (y también use un “fragmento de documento”).
- El bucle inverso es confuso a los desarrolladores junior. (Puede considerar eso una ventaja, dependiendo de su perspectiva).
¿Debería usarlo siempre?
Algunos desarrolladores usan el bucle for inverso por defectoa menos que haya una buena razón para avanzar en bucle.
Aunque las ganancias de rendimiento suelen ser insignificantes, grita:
“Solo haz esto con cada elemento de la lista, ¡no me importa el orden!”
Sin embargo, en la práctica eso es no en realidad una indicación confiable de la intención, ya que es indistinguible de aquellas ocasiones en las que hacer se preocupan por el orden, y realmente lo hacen necesitar para hacer un bucle en reversa. Entonces, de hecho, se necesitaría otra construcción para expresar con precisión la intención de “no me importa”, algo que actualmente no está disponible en la mayoría de los lenguajes, incluido ECMAScript, pero que podría llamarse, por ejemplo, forEachUnordered()
.
Si el orden no importa, y eficiencia es una preocupación (en el bucle más interno de un juego o motor de animación), entonces puede ser aceptable usar el bucle for inverso como su patrón de acceso. Solo recuerda que ver un bucle for inverso en el código existente no significa necesariamente que el orden irrelevante!
Era mejor usar forEach()
En general, para código de nivel superior donde claridad y seguridad son mayores preocupaciones, anteriormente recomendé usar Array::forEach
como su patrón predeterminado para bucles (aunque en estos días prefiero usar for..of
). Razones para preferir forEach
sobre un bucle inverso son:
- Es más claro de leer.
- indica que i no se va a desplazar dentro del bloque (que siempre es una posible sorpresa escondida en largas
for
ywhile
bucles). - Le da un alcance gratuito para los cierres.
- Reduce la fuga de variables locales y la colisión accidental con (y la mutación de) variables externas.
Luego, cuando vea el bucle for inverso en su código, eso es una pista de que está invertido por una buena razón (quizás una de las razones descritas anteriormente). Y ver un bucle for de avance tradicional puede indicar que se puede producir un cambio.
(Si la discusión sobre la intención no tiene sentido para usted, entonces usted y su código pueden beneficiarse al ver la conferencia de Crockford sobre Estilo de programación y tu cerebro.)
¡Ahora es incluso mejor usar for..of!
Hay un debate sobre si for..of
o forEach()
son preferibles:
-
Para obtener la máxima compatibilidad con el navegador,
for..of
requiere un polirelleno para los iteradores, lo que hace que su aplicación sea un poco más lenta de ejecutar y un poco más grande de descargar. -
Por esa razón (y para fomentar el uso de
map
yfilter
), algunas guías de estilo front-end prohibiciónfor..of
¡completamente! -
Pero las preocupaciones anteriores no se aplican a las aplicaciones Node.js, donde
for..of
ahora está bien respaldado. -
Y además
await
No funciona en el interiorforEach()
. Usandofor..of
es el patrón más claro en este caso.
Personalmente, tiendo a usar lo que parezca más fácil de leer, a menos que el rendimiento o la minimización se hayan convertido en una preocupación importante. Así que en estos días prefiero usar for..of
en vez de forEach()
pero siempre usaré map
o filter
o find
o some
cuando sea aplicable. (Por el bien de mis colegas, rara vez uso reduce
.)
¿Como funciona?
for (var i = 0; i < array.length; i++) { ... } // Forwards
for (var i = array.length; i--; ) { ... } // Reverse
Notarás que i--
es la cláusula intermedia (donde normalmente vemos una comparación) y la última cláusula está vacía (donde normalmente vemos i++
). Eso significa que i--
también se utiliza como el condición para la continuación. Crucialmente, se ejecuta y verifica antes de cada iteración.
-
¿Cómo puede empezar en
array.length
sin explotar?Porque
i--
carreras antes de cada iteración, en la primera iteración en realidad accederemos al elemento enarray.length - 1
que evita cualquier problema conMatriz fuera de los límitesundefined
elementos. -
¿Por qué no deja de iterar antes del índice 0?
El ciclo dejará de iterar cuando la condición
i--
evalúa a un valor falso (cuando da 0).El truco es que a diferencia
--i
el finali--
decrementos del operadori
pero da el valor antes de el decremento Su consola puede demostrar esto:> var i = 5; [i, i--, i];
[5, 5, 4]
Así que en la iteración final, i fue previamente 1 y el
i--
expresión lo cambia a 0 pero en realidad rinde 1 (veracidad), y así pasa la condición. En la próxima iteracióni--
cambios i a -1 pero rinde 0 (falsey), lo que provoca que la ejecución abandone inmediatamente la parte inferior del ciclo.En los reenvíos tradicionales de bucle,
i++
y++i
son intercambiables (como señala Douglas Crockford). Sin embargo, en el bucle for inverso, debido a que nuestro decremento es también nuestra expresión de condición, debemos apegarnos ai--
si queremos procesar el elemento en el índice 0.
Trivialidades
A algunas personas les gusta dibujar una pequeña flecha en el reverso. for
loop, y termina con un guiño:
for (var i = array.length; i --> 0 ;) {
Los créditos van a WYL por mostrarme los beneficios y los horrores del bucle for inverso.
Pedro Mortensen
Alguno Cuso de lenguajes de estilo foreach
para recorrer las enumeraciones. En JavaScript esto se hace con el for..in
estructura de bucle:
var index,
value;
for (index in obj) {
value = obj[index];
}
Hay una trampa. for..in
recorrerá cada uno de los miembros enumerables del objeto y los miembros de su prototipo. Para evitar leer valores que se heredan a través del prototipo del objeto, simplemente verifique si la propiedad pertenece al objeto:
for (i in obj) {
if (obj.hasOwnProperty(i)) {
//do stuff
}
}
Además, ECMAScript 5 ha añadido un forEach
método para Array.prototype
que se puede usar para enumerar sobre una matriz usando una devolución de llamada (el polyfill está en los documentos, por lo que aún puede usarlo para navegadores más antiguos):
arr.forEach(function (val, index, theArray) {
//do stuff
});
Es importante tener en cuenta que Array.prototype.forEach
no se rompe cuando regresa la devolución de llamada false
. jQuery y Subrayado.js proporcionar sus propias variaciones en each
para proporcionar bucles que se pueden cortocircuitar.
para… de | paraCada | mapa
Usando la sintaxis moderna de JavaScript para iterar a través de matrices
const fruits = ['🍎', '🍋', '🍌' ]
👉🏽 para… de
for (const fruit of fruits) {
console.log(fruit) // '🍎', '🍋', '🍌'
}
👉🏽 paraCada uno
fruits.forEach(fruit => {
console.log(fruit) // '🍎', '🍋', '🍌'
})
👉🏽 mapa
*Diferente de los dos anteriores, map() crea una nueva matriz y espera que usted devolver algo después de cada iteración.
fruits.map(fruit => fruit) // ['🍎', '🍋', '🍌' ]
🛑 Importante: Como mapa() está destinado a devolver un valor en cada iteración, es un método ideal para transformar elementos en matrices:
fruits.map(fruit => 'cool ' + fruit) // ['cool 🍎', 'cool 🍋', 'cool 🍌' ]
Por otra parte, para… de y para cada( ) no necesitan devolver nada y es por eso que normalmente los usamos para realizar tareas lógicas que manipulan cosas externas.
Por así decirlo, encontrará instrucciones if (), efectos secundarios y actividades de registro en estos dos.
👌🏾 CONSEJO: también puede tener el índice (así como la matriz completa) en cada iteración en sus funciones .map() o .forEach().
Solo pásales argumentos adicionales:
fruits.map((fruit, i) => i + ' ' + fruit)
// ['0 🍎', '1 🍋', '2 🍌' ]
fruits.forEach((f, i, arr) => {
console.log( f + ' ' + i + ' ' + arr )
})
// 🍎 0 🍎, 🍋, 🍌,
// 🍋 1 🍎, 🍋, 🍌,
// 🍌 2 🍎, 🍋, 🍌,
Uso para… de bucle. Ver w3schools.com/JS/js_loop_forof.asp
– Codemaster Unido
25 de agosto a las 15:28
@CodemasterUnited La pregunta ya ha sido respondida.
–Sunderam Dubey
25 ago a las 15:33
Casi duplicado de (pero un poco más general que) “Recorrer una matriz en JavaScript”.
– fuera
17 oct a las 2:15