If you're new to JavaScript (or it's been a while since you looked at array iteration in JavaScript), you probably want to understand all the options that are available to you.

NOTE: This article assumes a familiarity with ES6 arrow functions and the let keyword.

Old School

One of the first concepts taught with arrays is iteration - looping through each element in the array. Historically, this has been done in JavaScript using a standard for loop.

    let array = ["a", "b", "c"];
    for (let index = 0; index < array.length; ++index) {
        let element = array[index];
        console.log(element);
    }

If you don't want to be bothered with the index variable and boundary condition checking, you can use the forEach method.

    let array = ["a", "b", "c"];
    array.forEach(element => {
        console.log(element);
    });

New School

This is how things were done for a long time, but ES6 added a new for...of statement:

    let array = ["a", "b", "c"];
    for (let element of array) {
        console.log(element);
    }

The new statement provides a simpler approach to iterating over the elements in the array. Using for...of, you don't need to worry about the index variable or the array boundaries and you also don't need the additional function that's required by forEach. But what if you want the index value for each element?

    let array = ["a", "b", "c"];
    for (let [index, element] of array.entries()) {
        console.log(index, element);
    }

For each element in your array, the entities function will generate another array containing the element's index position and a reference to the element. The example above uses destructuring to assign those values to the index and element variables.

Specialization

Although they are not new, JavaScript provides three higher-order functions for iterating over arrays: filter, map, and reduce. All three functions operate on an existing array and repackage it's elements in some way.

Filter

The filter function provides a way to selectively remove elements from an array by evaluating each element and generating a boolean result. Let's say we have a list of names that we want to filter so it only includes people whose name begins with "J". We could use a standard "old-school" loop.

    let names = ["Amy", "Fred", "John", "Jill", "Kim", "Steve", "Ted"];
    for (let index = names.length - 1; index >= 0; --index) {
        if (!names[index].startsWith("J")) {
            names.splice(index, 1);
        }
    }

Using the filter function, we can provide a much simpler solution. We call the filter function using our array, and pass a function that evaluates a single element and returns true if the element should remain in the array or false if the element should be removed (filtered). The function will be called once for each element in the array.

    let names = ["Amy", "Fred", "John", "Jill", "Kim", "Steve", "Ted"];
    names = names.filter(name => name.startsWith("J"));

Not only is the second method simpler, it also avoids fussing with the logic that looped through our first array backwards to avoid problems with removing elements while also iterating the array.

Map

The map function allows us to transform each element in the array into a new element in another array. For example, we could take our list of names and transform each element into an HTML list item. First, we'll go old-school.

    let names = ["Amy", "Fred", "John", "Jill", "Kim", "Steve", "Ted"];
    let elements = [];
    for (let index = 0; index < names.length; ++index) {
        let element = document.createElement("li");
        element.innerText = names[index];
        elements.push(element);
    }

Then we'll update the example using map. We will need to provide a function that takes the name string and returns a newly-created <li> element. Each element that's returned from this function will be appended to a new array. Again, the function will be called once for each element in the array.

    let names = ["Amy", "Fred", "John", "Jill", "Kim", "Steve", "Ted"];
    let elements = names.map(name => {
        let element = document.createElement("li");
        element.innerText = name;
        return element;
    });

Voila! We've transformed an array of names into an array of list items.

Reduce

The reduce function can take a little getting used to. It will evaluate each element in the array and generate a single aggregated result based on all the elements. In this example, let's consider an array of hiking objects. Each object has a distance property and we want to determine the total distance for all hikes.

    let hikes = [{
        location: "Boston",
        distance: 5.1
    }, {
        location: "Cleveland",
        distance: 2.3
    }, {
        location: "Houston",
        distance: 7.6
    }];

    let totalDistance = 0;
    for (let index = 0; index < hikes.length; ++index) {
        totalDistance += hikes[index].distance
    }

The reduce function will again take a function as it's first parameter, but the function receives two values - the aggregated result so far, and an element from the array. The second parameter for the reduce function provides an initial value for the aggregated result.

    let initialDistance = 0;
    let totalDistance = hikes.reduce((partialResult, hike) => {
        return partialResult + hike.distance;
    }, initialDistance);

Other examples of using reduce might count the number of elements in an array that meet some condition, or it might aggregate several objects into a "summary" object.

Summary

If you've only been using simple for loops with index variables to iterate arrays, now is a great time to begin experimenting with some alternatives. Here are a few exercises you can work through to become more familiar with these other approaches to iteration.

  1. Write your own filter function that uses for...of to iterate an array and remove unwanted elements. Your filter function can take two parameters: an input array, and a filtering function that receives a single element as the input and returns a boolean value to indicate whether or not to filter the element. The filter function should return a new array.
  2. Write your own map function that uses for...of to iterate an array and return a new array of transformed elements. Your map function should take two parameters: an input array, and a transform function that receives a single element as the input and returns a transformed element. The map function should return a new array.
  3. I'll let you guess what the third exercise is...
  4. How would you use the three higher-order Array methods to implement other iterative Array methods, such as Array.every(), Array.find(), and Array.some()? (MDN provides documentation on the various Arraymethods.)