Sunday, 3 March, 2019 UTC


Summary

If you've been writing JavaScript for even a short amount of time, you're probably still aware of how quickly the language is changing. Given all of these changes, that means there are also multiple ways to perform the same function. In this case I'm referring to looping over arrays using a for-each construct.
So what's the best way to do it? That question depends on a few things, like what JS version you're using, if you can use instance methods, etc. In this article I'll be exploring a number of ways to loop over arrays in JS.

Array's forEach Method

A widely supported method (except for in IE 8, unsurprisingly) is the Array.prototype.forEach method. It works by accepting a callback function with the parameters currentValue, index, and array. In many cases, only the currentValue and index parameters are used.
Here is an example:
let items = ['one', 'two', 'three', 'four'];  
items.forEach(function(val, idx) {  
    console.log(`${idx}: ${val}`);
});

// Output:
//
// 0: one
// 1: two
// 2: three
// 3: four
This is a great method due to its simplicity and clean syntax, although there are some downsides to it. Most notably, it's difficult to break out of this loop, unlike the built-in for loop where you can use the break keyword. With forEach you must throw an exception in order to exit the loop early.
As the MDN documentation points out, if you need to break out of a forEach loop, then this method is the wrong tool. In this case, some better options would be:
  • Built-in for loop (detailed below)
  • Built-in for-of loop (detailed below)
  • Array.prototype.every()
  • Array.prototype.some()
  • Array.prototype.find()
  • Array.prototype.findIndex()
The Array.prototype.* methods above can exit their loops by returning a truthy value that tells the loop if it should continue on.
The forEach method is good for when you have very simple looping requirements, and you don't need a lot of control over the actual looping behavior. However, this simplicity comes at a cost. It's about 95% slower than the built-in for loop, but for most people this slowdown will be insignificant.

Built-in for Loop

The built-in for loop (also known as a simple for loop) is probably the most well-known of the options since it works the same way in JavaScript as in many other languages. The syntax is as follows:
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
This kind of for loop has a number of advantages:
  • It's familiar to most programmers
  • Control loop continuation break and continue keywords
  • Control counter direction (via ++i or --i) and rate (i.e. i+2)
  • Partial looping (i.e. for (let i = 0; i < items.length/2; ++i))
With this much control over your loop, you also have to deal with its verbose syntax, which is why it's often avoided for simpler use-cases.
Note that the example shown above assumes you're using ES6 JavaScript, otherwise you'll need to declare the i variable using var and outside of the loop itself.

Built-in for-in Loop

Probably the most often misunderstood forms of looping in JavaScript is the for-in loop. At first glance it seems like you can use this to loop through each index in an array, but it's actually meant to loop through the enumerable property names of an object, and not necessarily just indexes.
For example, here is how it's used with arrays:
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
And here is how it is meant to be used with objects:
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
Many developers will actually explicitly advise against using this for iterating over arrays, especially if the order is important since order is not guaranteed.
If you want to loop over an array with this style of syntax, then for-of is recommended, which is the focus of the next section.

Built-in for-of Loop

The for-of loops have a very similar syntax to for-in, which we just saw. However, they main difference is that it iterates over iterable objects (like Strings, Arrays, Maps, Sets, etc.), whereas for-in iterates over all non-Symbol, enumerable properties of an object.
In practice, here is what that looks like:
let items = ['one', 'two', 'three', 'four'];  
for (let i of items) {  
    break;
    console.log(i);
}

// Output:
//
// one
// two
// three
// four
Notice that the i variable is no longer the index, but instead it's the actual array value. And since it only works on iterables, we can no longer use an object:
let obj = {hi: 'bye', one: 'two', foo: 'bar'};  
for (let o of obj) {  
    console.log(o);
}

// Output:
//
// TypeError: obj is not iterable
In terms of syntax and functionality, this is a bit of a compromise between the Array.forEach function and built-in for loop since the syntax is cleaner than the simple for loop, and it still allows you to use loop "control" keywords like break and continue, unlike forEach.
Another nice feature is that it works well with generators, so you can more easily take advantage of this in your loops:
function* myWords() {  
    yield 'foo';
    yield 'bar';
    yield 'baz';
}

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

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

Conclusion

As you can see, there are quite a few ways to perform a for-each loop over an array in JavaScript, and the construct you choose largely depends on what you want to accomplish and your specific use-case.
In this article we saw how to iterate over arrays using Array.forEach, built-in for loops, for-in loops, and for-of loops. Feel free to leave a comment below with any critiques or improvements that you see.