ES6, For loops? Forget it!

Working with arrays, we usually fill in our code with loops, cases such as...

“Check that an element is in array...”

“Calculate total sales, if it's more than a given amount then offer free shipping costs...”

“Get annual sales average...”

“If an item in a display matrix is marked red, trigger alarm...”

“Close order when all items have been sent...”

What do we do in ES5 JavaScript? Use loops and keep going. What drawbacks does this have?

  • Worse readability on code.
  • More prone to errors.
  • We're repeating the same code over and over.

Another option is to use a library like lodash, but... Is there any way to do this without third party libraries? The answer is yes! JavaScript ES6 has a lot of cool helper functions, some of them well known (such as map, reduce...) and other less well known ones. In this post we're going to review the most important ones to help improve the readability of your code as well as its maintenance.

Iterators

The example array that we are going to use:

Your website allows multiple bookings from other sites. Once you have the response from the server, you want to check that everything goes right. This is why the server response contains an array with the results of each booking, so you are able to check if any of them have failed.

The array that you're working on:

Input:

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

"True" returns when every item matches the condition. This method saves you from implementing a loop with if - break.

Assumption:

Let's check if everything has succeeded:

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

console.log(allSucceeded);

The result:

Every Result

Codepen sample

Filter

It allows retrieving those elements that match a given condition.

Let's retrieve all bookings that haven't succeeded:

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

console.log(unsucceededBookings);

The result:

Filter Result

Codepen sample

Another example could be: find all bookings higher than €500

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

console.log(bookingsVip);

The result:

Filter Result Bigger Than

Codepen sample

Find

It returns the first element that matches a given condition.

What if we want to find the first element that matches a condition? For example, we detect a frequent customer and we want to reward them. Let's search for the first booking with a standard room and offer a free premium upgrade. How can we find the first standard room booking?

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

console.log(booking.id);

The result:

Find Result

Codepen sample

What will happen if no entry matches the search? It returns undefined:

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

console.log(booking);

Let's see the result:

Find No Match Result

Codepen sample

FindIndex

FindIndex works similarly to Find, it just returns the array index of the first element that matches the condition:

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

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

The result:

FindIndex Result

Codepen sample

What if no element matches the condition? In this case it returns -1.

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

console.log(index);

The result:

FindIndex No Match Result

Codepen sample

Map

It applies to every single array element. The purpose of this function is to modify each array element.

For example, a user sends a bonus discount and we have to apply a 10% discount to each booking. What can we do?

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

console.log(discountedBookings);

What would return?

Map Result

Codepen sample

For a more compact code, we have used ES7 spread operator. We can also assign a different value to the booking price and return it.

Reduce

Reduce is the "sibling" function of map. In this case, instead of returning an array, it returns the total. In other words, it applies the function of accumulating the result.

Let's add up the prices of all bookings in array:

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

console.log(totalPrice);

What would return?

Reduce Result

Codepen sample

Some

Some is similar to Every, but in this case "true" returns if one of the elements almost matches the condition.

An example: let's find out if the customer has at least one 'superior' booking:

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

console.log(hasAnySuperiorRoom);

What would return?

Some Result

Codepen sample

Join us with a new iterator: Set

How many times haven't we wanted to create an array with unique items? The most common approach is to generate a new array, iterating element by element, checking that the item hasn't been added already. One of the principal features of Set is that a value can only occur once, so it prevents double items.

For example, let's create a new Set from a bookings array and a new booking that happened more than once:

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);

As a result we can see that the item has only been added once:

Set Result

Codepen sample

Let's see its principal methods, like the array ones:

Delete

We have already seen the Add method to add new items to our Set. With the Delete method we remove a set value. If it's removed from the set, it will return true. In case it doesn't exist, it will return false.

Let's remove the new booking that we have created in the previous example:

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);

The result would be:

Set Delete Result

Codepen sample

Size

The Size property is equivalent to array Length to check out the Set size. Let's see the total amount of elements of our bookings Set:

const uniqueBookings = new Set(bookings);

console.log(uniqueBookings.size);

Let's see the result:

Set Size Result

Codepen sample

Has

To check that an element is already on Set, Has is the appropiate method. This method returns true or false depending on if the element has already been set. For example, we're going to add, like before, a new booking and check if it has indeed been added:

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));

This would be the result:

Set Has Result

Codepen sample

Clear

If we want to empty Set without creating a new one, we can do it by using the Clear method. Let's empty the set of bookings that we have created:

const uniqueBookings = new Set(bookings);

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

We can check that Set is empty:

Set Empty

Codepen sample

Conclusion

In this article we have reviewed the principal iterators that we can find in ES6. Are there any that you didn't know about before? Which one is your favorite? Any useful ones that we haven't discussed yet? We really appreciate your input and feedback on this post.

I hope that you find this article useful, and remember, before looping or using third party libraries such as lodash, have a look at this cheat sheet and think to yourself: Can I work around the loops?

About Basefactor

We are a team of Javascript experts. If you need coaching or consultancy services, don't hesitate to contact us.

Doers/

Location/

C/ Pintor Martínez Cubells 5 Málaga (Spain)

General enquiries/

info@lemoncode.net

+34 693 84 24 54

Copyright 2018 Basefactor. All Rights Reserved.