Ya vimos que una collection (array de objetos) es una estructura muy poderosa ya que nos permite organizar en una lista ordenada, un montón de objetos que representan entidades como usuarios, productos, lugares.

Cuando hacemos búsquedas en Google Maps, lo que estamos viendo es un array de lugares que se dibujan en la pantalla.
1const restaurantes = [
2 {
3 name: "Loló",
4 rating: 4.5,
5 reviews: 849,
6 price: "$$",
7 cuisine: "Mexican",
8 address: "974 Valencia St",
9 description: "Creative Mexican chow in colorful space",
10 openUntil: "11:00 PM",
11 coordinates: { lat: 37.7569, lng: -122.4211 }
12 },
13 {
14 name: "Eric's Restaurant",
15 rating: 4.3,
16 reviews: 254,
17 price: "$",
18 cuisine: "Chinese",
19 address: "1500 Church St",
20 description: "Chinese food in a casual atmosphere",
21 openUntil: "9:30 PM",
22 coordinates: { lat: 37.7451, lng: -122.4264 }
23 },
24 {
25 name: "Firefly Restaurant",
26 rating: 4.5,
27 reviews: 364,
28 price: "$$$",
29 cuisine: "American",
30 address: "4288 24th St",
31 description: "Modern comfort food",
32 openUntil: "9:00 PM",
33 coordinates: { lat: 37.7511, lng: -122.4333 }
34 }
35];Lógica en listas
Cuando manipulamos listas nos encontramos con el problema de que en muchas ocasiones queremos aplicar cierta lógica a cada ítem de nuestra lista.
Por ejemplo, si tenemos una lista de usuarios de nuestro sistema y queremos saber cuales tienen mascotas para ofrecerles un producto, ¿cómo podemos preguntar en cada objeto cuantas mascotas tiene cada usuario?
1const usuarios = [
2 {
3 id: "hj12ds92j",
4 nombreCompleto: "Juan Pérez",
5 ciudad: "Buenos Aires",
6 mascotas: ["Firulais", "Michi"],
7 email: "juan.perez@gmail.com"
8 },
9 {
10 id: "kf98as71p",
11 nombreCompleto: "Ana Gómez",
12 ciudad: "Bogotá",
13 mascotas: [],
14 email: "ana.gomez@gmail.com"
15 },
16 {
17 id: "mn63tr45q",
18 nombreCompleto: "Carlos Ramírez",
19 ciudad: "Ciudad de México",
20 mascotas: ["Max", "Luna"],
21 email: "carlos.ramirez@gmail.com"
22 },
23 {
24 id: "zx75lg29v",
25 nombreCompleto: "María Torres",
26 ciudad: "Oaxaca",
27 mascotas: ["Bobby"],
28 email: "maria.torres@gmail.com"
29 },
30 {
31 id: "qw82hj64k",
32 nombreCompleto: "Pedro Fernández",
33 ciudad: "Lima",
34 mascotas: [],
35 email: "pedro.fernandez@gmail.com"
36 },
37 {
38 id: "ab39kl72f",
39 nombreCompleto: "Lucía Martínez",
40 ciudad: "Buenos Aires",
41 mascotas: ["Simba"],
42 email: "lucia.martinez@gmail.com"
43 },
44 {
45 id: "yt48mn90z",
46 nombreCompleto: "Jorge Rojas",
47 ciudad: "Bogotá",
48 mascotas: ["Nina", "Rocky"],
49 email: "jorge.rojas@gmail.com"
50 },
51 {
52 id: "uv91pq64w",
53 nombreCompleto: "Sofía Herrera",
54 ciudad: "Ciudad de México",
55 mascotas: [],
56 email: "sofia.herrera@gmail.com"
57 },
58 {
59 id: "op54xs31c",
60 nombreCompleto: "Diego López",
61 ciudad: "Oaxaca",
62 mascotas: ["Kira", "Tom"],
63 email: "diego.lopez@gmail.com"
64 },
65 {
66 id: "gh76bn83d",
67 nombreCompleto: "Valentina Castro",
68 ciudad: "Lima",
69 mascotas: ["Coco"],
70 email: "valentina.castro@gmail.com"
71 }
72];Lo que conocemos hasta ahora nos indica que podemos usar un if para preguntar por cada objeto y saber si tiene mascotas o no.
1if (usuarios[0].mascotas.length > 0) {
2 console.log(`El usuario ${usuarios[0].nombreCompleto} tiene mascotas.`);
3}
4
5if (usuarios[1].mascotas.length > 0) {
6 console.log(`El usuario ${usuarios[1].nombreCompleto} tiene mascotas.`);
7}
8
9if (usuarios[2].mascotas.length > 0) {
10 console.log(`El usuario ${usuarios[2].nombreCompleto} tiene mascotas.`);
11}
12
13if (usuarios[3].mascotas.length > 0) {
14 console.log(`El usuario ${usuarios[3].nombreCompleto} tiene mascotas.`);
15}
16
17if (usuarios[4].mascotas.length > 0) {
18 console.log(`El usuario ${usuarios[4].nombreCompleto} tiene mascotas.`);
19}
20
21if (usuarios[5].mascotas.length > 0) {
22 console.log(`El usuario ${usuarios[5].nombreCompleto} tiene mascotas.`);
23}
24
25if (usuarios[6].mascotas.length > 0) {
26 console.log(`El usuario ${usuarios[6].nombreCompleto} tiene mascotas.`);
27}
28
29if (usuarios[7].mascotas.length > 0) {
30 console.log(`El usuario ${usuarios[7].nombreCompleto} tiene mascotas.`);
31}
32
33if (usuarios[8].mascotas.length > 0) {
34 console.log(`El usuario ${usuarios[8].nombreCompleto} tiene mascotas.`);
35}
36
37if (usuarios[9].mascotas.length > 0) {
38 console.log(`El usuario ${usuarios[9].nombreCompleto} tiene mascotas.`);
39}Este código, aunque funciona, no parece muy escalable ¿no? Pensemos que pasa si tenemos 10.000 usuarios. O si, directamente, no sabemos cuantos usuarios tenemos en nuestro array.
1// esta linea la vamos a entender más adelante
2// pero básicamente lo que sucede es que el array
3// viene de otro lugar (una base de datos)
4// y no sabemos cuantas posiciones tiene.
5
6// Lo único que sabemos es que es un array y tiene
7// objetos como los que esperamos.
8const usuarios = baseDeDatos.dameTodosLosUsuarios();
9
10if (usuarios[0].mascotas.length > 0) {
11 console.log(`El usuario ${usuarios[0].nombreCompleto} tiene mascotas.`);
12}
13
14if (usuarios[1].mascotas.length > 0) {
15 console.log(`El usuario ${usuarios[1].nombreCompleto} tiene mascotas.`);
16}
17
18// etc...
19
20// acá esta lógica no sirve porque no sabemos si el array
21// de usuario tiene 10 o tiene 1 millon de usuarios.Necesitamos otra forma de hacer esto y por suerte JavaScript nos provee de una estructura que podemos usar para hacer esta pregunta sobre las mascotas en cada posición del array y sin repetir código: los bucles.
Bucles

Los bucles o loops (en ingles) son estructuras que nos permiten repetir un bloque de código y por eso van a ser especialmente útiles para resolver problemas como el de las listas que vimos anteriormente.
A continuación vamos a darle un vistazo a todos los bucles que existen en JavaScript para entender que función cumplen, pero ¡tranqui! No te desesperes todavía por entender como y cuando se usa cada uno. En las próximas clases vamos a meternos en cada uno de los bucles y a practicar mucho. Por ahora mirá los ejemplos y tratá de entender la idea general.
While
Para entender el propósito de los bucles, volvamos al ejemplo de las mascotas un momento.
1if (usuarios[0].mascotas.length > 0) {
2 console.log(`El usuario ${usuarios[0].nombreCompleto} tiene mascotas.`);
3}
4
5if (usuarios[1].mascotas.length > 0) {
6 console.log(`El usuario ${usuarios[1].nombreCompleto} tiene mascotas.`);
7}
8
9if (usuarios[2].mascotas.length > 0) {
10 console.log(`El usuario ${usuarios[2].nombreCompleto} tiene mascotas.`);
11}
12
13// etcEste código repite exactamente la misma lógica para cada posición del array. Lo único que cambia en cada if es el número de posición del array que revisa para saber si tiene mascotas o no. Si tan solo pudiéramos repetir esas lineas usando una variable para revisar cada posición del array... momento! Podemos.
El bucle while repite el código dentro del bloque mientras la condición sea verdadera.
1while(/* condicion */){
2 // Lo que esta acá se va a ejecutar una y otra vez
3 // mientras la condición sea cierta
4}Entonces, si escribimos un while como este:
1const num = 3;
2
3while(num < 6){
4 // esto se va a trabar acá
5 console.log("El valor de num es", num);
6}
7
8console.log("Esto nunca se va a ejecutar");Nuestro programa va a quedarse dentro del while y no va a continuar. Esto sucede porque la condición (num < 6) siempre va a ser true, ya que num es una constante que nació siendo 3 y nunca va a cambiar de valor. Entonces, num siempre va a ser menor que 6 y eso le dice al while que siga repitiéndose infinitamente.
Si bien existen casos (avanzados) donde queremos que el bucle se ejecute para siempre y nunca salga de ahí (bucles infinitos), por lo general vamos a querer que un bucle se ejecute una x cantidad de veces y luego concluya para que nuestro código siga su recorrido.
Para aprovechar este mecanismo para el bien, necesitamos usar una variable que cambie de valor, para que en algún momento la condición que evalúa el while sea falsa, y así deje de ejecutarse una y otra vez.
1// arranca siendo 3
2let num = 3;
3
4// esto va a repetirse mientras sea menor que 6
5while(num < 6){
6 // acá lo mostramos
7 console.log("El valor de num es", num);
8 // y acá lo modificamos para que num avance
9 // y en algún momento sea mayor a 6
10 num++;
11}
12
13console.log("Ahora si, esto va a ejecutarse luego de que el while termine de hacer lo suyo");Usando una variable podemos hacer que la condición comience siendo verdadera y en algún momento pase a ser falsa. Que es justamente lo que necesitamos para recorrer nuestro array.
1// iniciamos esto en 0
2let i = 0;
3
4while (i < usuarios.length) {
5 // cada vez que esto se ejecuta
6 // el while va a chequear si i es menor
7 // a la cantidad de posiciones de nuestro array
8 // si es menor, va a ejecutar todo el bloque
9 // una vez más
10
11 // acá usamos la misma lógica pero en vez
12 // de escribir el número de posición
13 // usamos i para que ir recorriendo
14 // una a una cada posición
15 console.log("i vale", i)
16 if (usuarios[i].mascotas.length > 0) {
17 console.log(`El usuario ${usuarios[i].nombreCompleto} tiene mascotas.`);
18 }
19 // modificamos i para que sea igual a si mismo +1
20 i++;
21}De esta forma la primera vez i va a valer 0, la segunda va a valer 1, y así va a ir cambiando mientras sea menor a la cantidad de posiciones del array (usuarios.length).
Si nuestro array tiene 30 posiciones, la variable i va a cambiar hasta que llegue a 29 y esa va a ser la última vez que el while se va a ejecutar. En un array de 30 elementos el último va a ser array[29] porque arrancan desde el 0.
Do...While
Es una variante de while que primero ejecuta y después pregunta.
1// arranca siendo 3
2let num = 3;
3
4do {
5 console.log("El valor de num es", num);
6 num++;
7} while (num < 6);
8
9console.log("Terminó!");Este bucle se usa en casos muy específicos, donde tenemos que repetir una acción al menos una vez y no sabemos cuantas veces. El caso clásico es pedirle al usuario que ingrese un dato y no continuar con el resto del programa hasta que lo haga. El siguiente ejemplo es un poco avanzado pero es para que se entienda el uso y para que vean que solo se usa en casos muy particulares.
1let modoEspera;
2
3do {
4 console.log("Las entradas todavía no están disponibles");
5 modoEsperar = sigueElModoEsperaParaLasEntradas();
6 // esto va a chequear una vez y va a repetirse
7 // este chequeo hasta que la variable cambie;
8} while (modoEspera);
9
10console.log("Las entradas están disponibles");Si quisiera implementar la lógica de nuestros usuarios con mascotas podríamos sin problemas, pero van a notar que el código ya de entrada es un poco más difícil de entender.
1let i = 0;
2
3do {
4 if (usuarios[i].mascotas.length > 0) {
5 console.log(`El usuario ${usuarios[i].nombreCompleto} tiene mascotas.`);
6 }
7 i++;
8} while (i < usuarios.length);Además que tener el while al final, lo hace más difícil de leer, esto puede generarnos un error si el array que evaluamos no tiene ninguna posición. Como el chequeo es al final, la primera ejecución fallaría.
Intentá ejecutar el siguiente ejemplo:
1// ¿Por qué el array estaría vació? te preguntarás.
2// El array puede venir de otro lugar, por ejemplo:
3// una base de datos. Y quizás viene vacío.
4const usuarios = [];
5
6let i = 0;
7
8do {
9 if (usuarios[i].mascotas.length > 0) {
10 console.log(`El usuario ${usuarios[i].nombreCompleto} tiene mascotas.`);
11 }
12 i++;
13} while (i < usuarios.length);Esto arroja un error, que si usáramos el tradicional while, no ocurriría porque primero chequea la condición y después ejecuta el bloque.

Igual no te preocupes por el do...while, solo lo estamos repasando para que veas que hay varios tipos de bucles y todos sirven para cosas parecidas.
For...of
Este es mi favorito. Es el más fácil de leer, de escribir, es cortito y además está pensado para el caso más común de todo: recorrer listas.
1const numeros = [3, 90, 12, 6, 42, 21, 54, 15];
2
3for (const n of numeros) {
4 console.log(n);
5}Simple y elegante. Recorre el array de principio a fin (si está vacío no hace nada) y te asigna la posición en la variable que le digas (el iterador). Podemos usar const o let para el iterador porque en realidad no modifica la misma variable, crea una nueva variable (n en este caso) una y otra vez.
Este es el bucle que más uso y es porque la mayoría de las veces uso un bucle para recorrer un array de principio a fin y el for...of es ideal.
1for (const user of usuarios) {
2 if (user.mascotas.length > 0) {
3 console.log(`El usuario ${user.nombreCompleto} tiene mascotas.`);
4 }
5}For...in
For...in es parecido a for...of pero no te asigna el item del array directamente. Te asigna el índice.
1const numeros = [3, 8, 12, 5, 9, 20, 7, 15];
2
3for (const pos in numeros) {
4 console.log(pos);
5}
6// Si hacemos esto vamos a ver:
7// 0
8// 1
9// 2
10// 3
11// 4
12// 5
13// 6
14// 7Entonces si quisiera acceder a cada número tendríamos que hacer.
1const numeros = [3, 8, 12, 5, 9, 20, 7, 15];
2
3for (const pos in numeros) {
4 console.log(numeros[pos]);
5}
6// ahora si vamos a ver los números del array
7// 3
8// 8
9// 12
10// 5
11// 9
12// 20
13// 7
14// 15Si, es confuso, veamos el ejemplo de nuestro array de usuarios.
1for (const indice in usuarios) {
2 const user = usuarios[indice];
3 // Obtenemos el objeto usuario usando el índice
4 if (user.mascotas.length > 0) {
5 console.log(`El usuario ${user.nombreCompleto} tiene mascotas.`);
6 }
7}Este bucle se usa para recorrer listas donde necesitamos saber en que posición del array estamos. Vamos a ver más casos útiles luego, pero la verdad es que donde se luce for...in es: recorriendo objetos.
¿queeee? ¿se puede recorrer un objeto? En realidad podemos recorrer sus keys (claves) y de nuevo, sirve para casos específicos donde en vez de un array tenemos un objeto y queremos hacer algo con todas sus propiedades.
Este ejemplo un poquitín avanzado pero muestra un buen caso de uso de for..in.
1// Tenemos un objeto que tiene una propiedad
2// por cada usuario. Este uso de los objetos se
3// suele llamar: mapa
4
5// En este caso es un mapa id de: usuario -> número de mascotas
6const mascotasPorUsuario = {
7 hj12ds92j: 2,
8 kd49fs27a: 1,
9 lk34mc92z: 3,
10 mn73gb45d: 0,
11 qw84kp12x: 4,
12 pr12mc97v: 1,
13 xb49wd28y: 2,
14 pd20zy98r: 0,
15 cn59hd21s: 5,
16 vd28ka34o: 3,
17};
18
19// Esto se usa para lógicas donde necesitamos la data
20// organizada de esta forma para no andar
21// iterando arrays enormes una y otra vez.
22
23// Igual, tranqui que vamos a ver más adelante
24// en que casos van a aparecer estos mapas.
25// Pero si queremos saber que usuario tiene más mascotas
26// en base a este objeto podemos iterarlo con for...in
27
28let idConMasMascotas = null;
29let maxMascotas = 0;
30
31for (const id in mascotasPorUsuario) {
32 if (mascotasPorUsuario[id] > maxMascotas) {
33 maxMascotas = mascotasPorUsuario[id];
34 idConMasMascotas = id;
35 }
36}
37
38console.log(
39 `El ID con más mascotas es ${idConMasMascotas}, con ${maxMascotas} mascotas.`
40);For (clásico)
Este se llama simplemente: for. Es el más conocido ya que existe, así tal cual, en muchos lenguajes y es el que te enseñaban cuando aprendías programación antes. Es un poco más enroscado porque tiene varias partes y la verdad es que se usa en casos muy, muy, muy específicos donde no te alcanza con for...of, for...in o un simple while. Vamos a profundizar más en este for en otra clase para terminar de entenderlo. Por ahora veamos como sería recorrer el array de usuarios con mascotas.
1for (let i = 0; i < usuarios.length; i++) {
2 const u = usuarios[i];
3
4 if (u.mascotas.length > 0) {
5 console.log(`El usuario ${u.nombre} tiene mascotas.`);
6 }
7}De todas formas hace lo mismo que los otros bucles.
Conclusión
Los bucles (o loops) hacen todos mas o menos lo mismo. Repiten un bloque una cantidad de veces determinada y se pueden manejar de distintas formas. La mayoría de las veces los vamos a usar para recorrer arrays. No te desesperes por entender todos los casos donde podría usar bucles porque es tan básico como el if. Llegado el caso, no vas a tener otra opción y la decisión va a ser si usar un while o un for. A medida que vayas viendo más y más código vas a ver en que casos se usan y te vas a acostumbrar rápidamente.