JavaScript ES6 no más bucles FOR


Cuando trabajamos con arrays es muy normal que llenemos nuestro código de bucles, casos como...

“Comprobar si un elemento está en el array...”

“Calcular  la suma de ventas, y si es mayor que una cantidad dada para ofrecer gastos envío cero...”

“Sacar la media de ventas anuales...”

“En una matriz de indicadores, si uno de ellos está en rojo dispara la alarma...”

“Cerrar el pedido cuando todos los artículos hayan sido enviados...”

 

¿Qué solemos hacer JavaScript ES5? Tirar de bucle y ‘palante’, ¿Que desventajas tiene esto?

- El código es menos legible.

- Es más fácil que nos equivoquemos.

- Estamos repitiendo una y otra vez trozos de código parecidos.

Otra opción era utilizar una librería como lodash, pero... ¿no hay forma de hacer lo mismo sin tener que usar librerías de terceros? La respuesta es sí, con JavaScript ES6 tenemos un montón de métodos de ayuda que están muy bien, algunos son bien conocidos (map, reduce...) y otros no tanto, en este post damos un buen repaso a los más importantes para ayudarte a que tu código sea más fácil de leer y mantener.

Iteradores

El array de ejemplo que vamos a usar:

Tu web permite hacer reservas multiples de varios sitios, una vez que recibes la respuesta de los servidor quieres comprobar que todo ha ido bien, para ello tienes un array de respuesta y quieres ver si alguna ha fallado.

El array con el que trabajas:

Entrada:

const bookings = [
  { id: 23453, price: 250, room: 'standard', prepaid: false, succeeded: true },
  { id: 56456, price: 150, room: 'superior', prepaid: false, succeeded: true },
  { id: 43243, price: 550, room: 'standard', prepaid: true, succeeded: false },
  { id: 23223, price: 550, room: 'standard', prepaid: true, succeeded: true },
  { id: 89232, price: 650, room: 'superior', prepaid: true, succeeded: false }
];

 

Every

Devuelve true si todos los elementos del array cumplen con una condición dada. Este método te ahorra implementar bucles for con un if - break.

Supuesto:

Vamos a comprobar que todas han tenido éxito:

const allSucceeded = bookings.every(booking => booking.succeeded);

console.log(allSucceeded);

El resultado:

Ejemplo en Codepen

 

Filter

Te permite extraer de un array aquellos elementos que cumplan cierta condición.

Vamos a extraer todas las reservas que no han tenido éxito:

const unsucceededBookings = bookings.filter(booking => !booking.succeeded);

console.log(unsucceededBookings);

El resultado:

Ejemplo en Codepen

 

Otro ejemplo podría ser, dame las reservas de más de 500 €:

const bookingsVip = bookings.filter(booking => booking.price > 500);

console.log(bookingsVip);

El resultado:

Ejemplo en Codepen

 

Find

Te devuelve el primer elemento que cumpla con una condición dada.

 

¿Y si lo que queremos es buscar el primer elemento que cumpla una condición? Por ejemplo, detectamos que tenemos un cliente

frecuente y queremos tener un detalle con él, vamos a buscar la primera reserva que tenga habitación estándary le

ofreceremos un upgrade gratuito a premium. ¿Cómo encontramos la primera reserva con habitación estándar?

const booking = bookings.find(booking => booking.room === 'standard');

console.log(booking.id);

El resultado:

Find 1.png

Ejemplo en Codepen

 

 

¿Qué pasaría si no hay ninguna entrada que cumpla con lo que buscamos? Nos devuelve undefined:

const booking = bookings.find(booking => booking.room === 'suite');

console.log(booking);

Vemos el resultado:

Find 2.png

 

Ejemplo en Codepen

 

FindIndex

FindIndex funciona de una manera similar a Find, sólo que te devuelve el índice del array del primer elemento que cumple con la condición:

const index = bookings.findIndex(booking => booking.room === 'standard');

console.log(bookings[index].id);

El resultado:

Ejemplo en Codepen

 

¿Qué pasa si ningún elemento cumple con la condición? En ese caso devuelve -1:

const index = bookings.findIndex(booking => booking.room === 'suite');

console.log(index);

El resultado:

Ejemplo en Codepen

 

Map

Aplica a cada elemento del array una función cuyo fin es modificar cada elemento del array.

 

Por ejemplo, resulta que el cliente ha introducido un cupón de descuento y debemos de hacerle un descuento del 10% en cada reserva, lo que podemos hacer:

const discount = 10;
const discountedBookings = bookings.map(booking => ({
  ...booking,
  price: booking.price * (1 - (discount / 100))
}));

console.log(discountedBookings);

Lo que devolvería:

Ejemplo en Codepen

 

Para tener un código más compacto hemos usado el spread operator de ES7. Otra opción habría sido asignar a booking price otro valor y devolverlo.

 

Reduce

Reduce es la función "hermana" de map, en este caso en vez de devolver un array, lo que devuelve es un total, es decir aplica una función y va acumulando el resultado.

 

Vamos a sumar el total de € de las reservas que hay en el array:

const totalPrice = bookings.reduce((total, booking) => total + booking.price, 0);

console.log(totalPrice);

Lo que devolvería:

Ejemplo en Codepen

 

Some

Some es parecida a Every, pero en este caso te devuelve true si al menos uno de los elemento cumple con la condición que le pasamos.

 

Como ejemplo vamos a buscar si el cliente tiene al menos una reserva 'superior' realizada:

const hasAnySuperiorRoom = bookings.some(booking => booking.room === 'superior');

console.log(hasAnySuperiorRoom);

Lo que devolvería:

Ejemplo en Codepen

 

Se nos une un nuevo iterador: Set

¿Cuántas veces hemos querido crear un array con datos únicos? La aproximación más común es generar un nuevo array iterando elemento a elemento comprobando que no estuviese ya metido. Una de las principales características de Set es que un valor sólo puede estar una sola vez, por lo que resulta bastante conveniente para eliminar valores duplicados.

 

Como ejemplo vamos a crear un nuevo Set a partir del array de bookings y añadir un nuevo booking más de una vez:

const newBooking = {
  id:98441,
  price: 350,
  room: 'standard',
  prepaid: false,
  succeeded: true
};

const uniqueBookings = new Set(bookings);

uniqueBookings.add(newBooking);
uniqueBookings.add(newBooking);
uniqueBookings.add(newBooking);
uniqueBookings.add(newBooking);

console.log(uniqueBookings);

Como resultado vemos que sólo está añadido una única vez:

Ejemplo en Codepen

Veamos sus principales métodos semejantes al de los arrays:

 

delete

Ya hemos visto el método Add para añadir nuevos elementos a nuestro Set. Con el método Delete eliminamos un valor ya introducido. Si se ha eliminado del Set devolverá true, si no existía devolverá false.

Vamos a eliminar el nuevo booking que creamos en el ejemplo anterior:

const newBooking = {
  id:98441,
  price: 350,
  room: 'standard',
  prepaid: false,
  succeeded: true
};

const uniqueBookings = new Set(bookings);

uniqueBookings.add(newBooking);
console.log('Nuevo booking eliminado', uniqueBookings.delete(newBooking));
console.log('Eliminar nuevo booking de nuevo', uniqueBookings.delete(newBooking));
console.log(uniqueBookings);

El resultado sería:

Ejemplo en Codepen

 

size

La propiedad Size es la equivalente a Length de los arrays para comprobar el tamaño del Set. Veamos el total de bookings de nuestro Set de bookings:

const uniqueBookings = new Set(bookings);

console.log(uniqueBookings.size);

Veamos el resultado:

Ejemplo en Codepen

 

has

Para comprobar si Set tiene ya un valor el método Has es el apropiado. Este método nos devuelve true o false dependiendo de si el elemento ya está o no. Como ejemplo vamos a añadir, como anteriormente, un nuevo booking y comprobar si se ha añadido correctamente:

const newBooking = {
  id:98441,
  price: 350,
  room: 'standard',
  prepaid: false,
  succeeded: true
};

const uniqueBookings = new Set(bookings);

uniqueBookings.add(newBooking);
console.log(uniqueBookings.has(newBooking));

Este sería el resultado:

Ejemplo en Codepen

 

clear

Si queremos vaciar el Set sin tener que crear otro nuevo podemos hacerlo usando el método Clear. Vamos a vaciar el set que creamos de bookings:

const uniqueBookings = new Set(bookings);

uniqueBookings.clear();
console.log(uniqueBookings);

Vemos que el resultado el Set está vacío:

Ejemplo en Codepen

 

Conclusión

En este artículo hemos dado un buen repaso a los iteradores principales que te puedes encontrar en ES6 ¿Había alguno que no conocías? ¿ Cual es tu favorito? ¿ Alguno que tu encuentres útil y se nos haya pasado? Encantados de que participes en los comentarios de este post.

Espero que este artículo te haya sido de utilidad, y recuerda, antes de ponerte a meter bucles, o librerías tipo lodash, mira esta chuleta y piensa ¿Me lo puedo ahorrar?