You might not need a loop

In JavaScript, like any other language, there are several ways to achieve the same result, some being more suited to certain situations than others. One of the first concepts I learned about when learning to code was loops, and it seemed like the answer to almost everything.

Although loops are great for a lot of use cases, the JavaScript language has provided a suite of methods that can be used to achieve similar results in a more targeted, and sometimes more performant, way.

In this article, I want to cover some examples of where Array methods can be used to replace for loops (and by extension the forEach() method).

Modifying data with map()

If we want to perform an action on each item in an array and generate a new array with the resulting items, the map() is a great option.

The map() method is available on any Array and has three parameters - the current item in the array, the index (optional), and the original array (optional). Within the callback function, we can return whatever value we want to make up the new array that the map() function returns.

const newArray = myArray.map((current, index, array) => {
    // return item for newArray
})

Let’s take the example of the following array of articles, each with a title and rating property:

const articles = [
    { title: 'You might not need a loop', rating: 4 },
    ...
];

Let’s say we wanted to create a new array, but with each of the articles rated as 5 stars. We could do this using a basic for loop, which could look something like this:

const amazingArticles = [];

for (let i = 0; i < articles.length; i++) {
    const newArticle = Object.assign(articles[i], {rating: 5});
    amazingArticles.push(newArticle);
}

Although this yields the result we want, this logic could be better served by using the .map() method instead.

const amazingArticles = articles.map((article) => {
    return Object.assign(article, {rating: 5});
});

Filtering data with filter()

Sometimes, we want to ascertain whether and which items within an array satisfy a particular condition. We can do this with the filter() method.

The filter() method, like map(), has three parameters - the current item in the array, the index (optional), and the original array (optional). Unlike map(), what is returned is a boolean which determines whether or not to keep the item in the new array the filter() method returns.

const newArray = myArray.filter((current, index, array) => {
    // return true or false
});

Let’s take the example of the array of articles from before. What if we wanted to get all the articles in the array that are rated 3 and above? Again, we could do this with a for loop, but the filter() method is more suitable.

const highlyRatedArticles = articles.filter((article) => {
    return article.rating >= 3;
});

Testing conditions with every() and some()

With the filter() method, we can determine which items within an array satisfy a particular condition. But sometimes, we don’t need to know which items do or don’t satisfy the condition, we may just need to know if all or any of the items satisfy the condition. This is where the every() and some() methods come into play.

The every() and some() methods function very similarly to filter() method. They have the same parameters, and their callback function expects a boolean to be returned to determine whether the item meets the condition.

const every = myArray.every((current, index, array) => {
    // return true or false
});

const some = myArray.some((current, index, array) => {
    // return true or false
});

The key difference between these methods and filter() are in what the methods themselves return, i.e. in the above example what the values of the every and some variables would be.

Where the filter() method returns a new array of elements that meets the condition, the every() and some() methods return booleans.

The every() method will return true is every item within the array satisfies the condition. If only one item does not satisfy the condition, it will instead return false. The some() method, on the other hand, will return true if at least one item within the array satisfies the condition.

To loop or not to loop?

As I mentioned earlier, loops are a great tool for a lot of cases, and the existence of these new methods doesn't mean that loops shouldn't be used at all.

I think these methods are great because they provide code that is in a way self-documenting. When we use the filter() method instead of a for loop, it is easier to understand at first glance what the purpose of the logic is.

However, these methods have very specific use cases and may be overkill if their full value isn't being used. An example of this is the map() method, which can technically be used to replace almost any arbitray loop. If in our first example, we only wanted to modify the original articles array and not create a new, modified, amazingArticles, using this method would be unnecessary. It's important to use the method that suits each scenario, to make sure that we aren't over- or under-performing.

blog comments powered by Disqus