For-each sobre una matriz en JavaScript

Si ha estado escribiendo JavaScript incluso durante un breve período de tiempo, es probable que aún sepa lo rápido que cambia el idioma. Teniendo en cuenta todos estos cambios...

Si ha estado escribiendo JavaScript aunque sea por un corto período de tiempo, probablemente aún esté al tanto de la rapidez con la que cambia el idioma. Teniendo en cuenta todos estos cambios, eso significa que también hay múltiples formas de realizar la misma función. En este caso, me refiero al bucle sobre arreglos usando una construcción para cada uno.

Entonces, ¿cuál es la mejor manera de hacerlo? Esa pregunta depende de algunas cosas, como qué versión de JS está usando, si puede usar métodos de instancia, etc. En este artículo, exploraré varias formas de recorrer arreglos en JS.

Matriz para cada método

Un método ampliamente compatible (excepto en IE 8, como era de esperar) es el método Array.prototype.forEach. Funciona aceptando una función de devolución de llamada con los parámetros currentValue, index y array. En muchos casos, solo se utilizan los parámetros currentValue e index.

Aquí hay un ejemplo:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
let items = ['one', 'two', 'three', 'four'];
items.forEach(function(val, idx) {
    console.log(`${idx}: ${val}`);
});

// Output:
//
// 0: one
// 1: two
// 2: three
// 3: four

Este es un gran método debido a su simplicidad y sintaxis clara, aunque tiene algunas desventajas. Lo más notable es que es difícil salir de este bucle, a diferencia del bucle for integrado en el que puedes usar la palabra clave break. Con forEach debe lanzar una excepción para salir del bucle antes de tiempo.

Como señala la documentación de MDN, si necesita salir de un bucle forEach , entonces este método es la herramienta incorrecta. En este caso, algunas mejores opciones serían:

  • Bucle for incorporado (detallado a continuación)
  • Bucle for-of incorporado (detallado a continuación)
  • Array.prototype.every()
  • Array.prototipo.algunos()
  • Array.prototype.find()
  • Array.prototipo.findIndex()

Los métodos Array.prototype.* anteriores pueden salir de sus bucles devolviendo un valor real que le dice al bucle si debe continuar.

El método forEach es bueno cuando tiene requisitos de bucle muy simples y no necesita mucho control sobre el comportamiento real del bucle. Sin embargo, esta simplicidad tiene un costo. Es aproximadamente un 95% más lento que el bucle for incorporado, pero para la mayoría de las personas esta desaceleración será insignificante.

Bucle for integrado

El bucle for integrado (también conocido como bucle for simple) es probablemente la opción más conocida, ya que funciona de la misma manera en JavaScript que en muchos otros lenguajes. La sintaxis es la siguiente:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
let items = ['one', 'two', 'three', 'four'];
for (let i = 0; i < items.length; ++i) {
    console.log(`${i}: ${items[i]}`);
}

// Output:
//
// 0: one
// 1: two
// 2: three
// 3: four

Este tipo de bucle for tiene una serie de ventajas:

  • Es familiar para la mayoría de los programadores.
  • Palabras clave de continuación de bucle de control break y continue
  • Controle la dirección del contador (a través de ++i o --i) y la velocidad (es decir, i+2)
  • Bucles parciales (es decir, for (let i = 0; i < items.length/2; ++i))

Con tanto control sobre su ciclo, también tiene que lidiar con su sintaxis detallada, razón por la cual a menudo se evita para casos de uso más simples.

Tenga en cuenta que el ejemplo que se muestra arriba asume que está usando ES6 JavaScript; de lo contrario, deberá declarar la variable i usando var y fuera del bucle mismo.

Bucle for-in incorporado

Probablemente, la forma de bucle en JavaScript que se malinterpreta con mayor frecuencia es el bucle for-in. A primera vista, parece que puede usar esto para recorrer cada índice en una matriz, pero en realidad está destinado a recorrer los nombres de propiedades enumerables de un objeto, y no necesariamente solo los índices.

Por ejemplo, así es como se usa con arreglos:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
let items = ['one', 'two', 'three', 'four'];
for (let i in items) {
    console.log(`${i}: ${items[i]}`);
}

// Output:
//
// 0: one
// 1: two
// 2: three
// 3: four

Y así es como debe usarse con objetos:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
let obj = {hi: 'bye', one: 'two', foo: 'bar'};
for (let o in obj) {
    console.log(`${o}: ${obj[o]}`);
}

// Output
//
// hi: bye
// one: two
// foo: bar

Muchos desarrolladores desaconsejarán explícitamente usar esto para iterar sobre arreglos, especialmente si el orden es importante ya que el orden no está garantizado.

Si desea recorrer una matriz con este estilo de sintaxis, se recomienda for-of, que es el enfoque de la siguiente sección.

Bucle for-of incorporado

Los bucles for-of tienen una sintaxis muy similar a for-in, que acabamos de ver. Sin embargo, la principal diferencia es que itera sobre objetos iterables (como cadenas, matrices, mapas, conjuntos, etc.), mientras que for-in itera sobre todas las propiedades enumerables de un objeto que no son símbolos.

En la práctica, esto es lo que parece:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
let items = ['one', 'two', 'three', 'four'];
for (let i of items) {
    console.log(i);
}

// Output:
//
// one
// two
// three
// four

Tenga en cuenta que la variable i ya no es el índice, sino que es el valor real de la matriz. Y como solo funciona en iterables, ya no podemos usar un objeto:

1
2
3
4
5
6
7
8
let obj = {hi: 'bye', one: 'two', foo: 'bar'};
for (let o of obj) {
    console.log(o);
}

// Output:
//
// TypeError: obj is not iterable

En términos de sintaxis y funcionalidad, esto es un compromiso entre la función Array.forEach y el bucle for incorporado, ya que la sintaxis es más limpia que el simple bucle for, y todavía le permite usar repita las palabras clave "control" como break y continue, a diferencia de forEach.

Otra buena característica es que funciona bien con generadores, por lo que puedes aprovechar esto más fácilmente en tus bucles:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
function* myWords() {
    yield 'foo';
    yield 'bar';
    yield 'baz';
}

for (let w of myWords()) {
    console.log(w);
}

// Output:
//
// foo
// bar
// baz

Conclusión

Como puede ver, hay bastantes formas de realizar un bucle for-each sobre una matriz en JavaScript, y la construcción que elija depende en gran medida de lo que quiera lograr y su caso de uso específico.

En este artículo vimos cómo iterar sobre arreglos usando Array.forEach, bucles for integrados, bucles for-in y bucles for-of. Siéntase libre de dejar un comentario a continuación con cualquier crítica o mejora que vea.