Bucle sobre una matriz en JavaScript

10 minutos de lectura

Avatar de usuario de Dante1986
dante1986

¿Cómo puedo recorrer todas las entradas en una matriz usando JavaScript?

  • 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

Avatar de usuario de Patrik Akerstrand
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

avatar de usuario de joeytwiddle
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 con array.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 ES6 for ... 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 y while 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 y filter), algunas guías de estilo front-end prohibición for..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 interior forEach(). Usando for..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 en array.length - 1 que evita cualquier problema con Matriz fuera de los límites undefined 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 --iel final i-- decrementos del operador i 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ón i-- 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 a i-- 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.

Avatar de usuario de Peter Mortensen
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  🍎, 🍋, 🍌,

¿Ha sido útil esta solución?