2. `forEach`

forEach

When to use: When you want to perform an operation on every element in an array.

Recall the ever so common 'for loop':

var numbers = [1, 2, 3, 4, 5]; for (var i = 0; i < numbers.length; i++) { console.log(numbers[i]); }

This is a ton of syntax and incredibly laborious if we merely want to perform an action for each item in the array. That's where the forEach array helper comes in handy. Here is a first example:

var numbers = [1, 2, 3, 4, 5]; numbers.forEach(function (number) { console.log(number); });

As you can see, forEach is a function that takes an anonymous callback function as an argument and invokes this function for each item in the array. The first parameter in that anonymous callback function with be the current item in the array. As demonstrated below, the callback also takes 2 additional, optional parameters - the 'index' and 'array'.


forEach from scratch

Often times it's helpful to reverse engineer what we're learning to get a deeper understanding. Let's see if we can rebuild forEach from scratch. Here is what it might look like:

// Adding it to the Array's prototype so we can call it directly on arrays Array.prototype.myForEach = function (callback) { for (let i = 0; i < this.length; i++) { callback(this[i], i, this); } };

Note that we called it myForEach instead of forEach just to prove to you that we built a new method from scratch, entirely.

Go ahead and copy/paste this example below to see that it works:

// Adding it to the Array's prototype so we can call it directly on arrays Array.prototype.myForEach = function (callback) { for (let i = 0; i < this.length; i++) { callback(this[i], i, this); } }; var numbers = [1, 2, 3, 4, 5]; numbers.myForEach(function (number) { console.log(number); });

Here are a few things to note about our myForEach function (and forEach):

  • The parameter that we're calling callback is a placeholder for whatever function will get passed to myForEach when its invoked. In the case above, we passed in a function that logs number.
  • When we invoke callback inside of myForEach, we're passing in 3 arguments - this[i], i, and this. That's because that's just how forEach works:
    arr.forEach(function (currentValue, index, array) { // iterator });

Let's move into some exercises.


forEach Exercise 1

Refactor the following code to use forEach instead of a "for loop":

var saveUser = function (user) { console.log('saving', user.name); } var saveUsers = function () { var users = [ { id: 15, name: 'Bob' }, { id: 23, name: 'Jimbo' }, { id: 35, name: 'Cathy' } ]; for (var i = 0; i < users.length; i++) { saveUser(users[i]); } }
Click to See Answer
var saveUser = function (user) { console.log("saving", user.name); }; var saveUsers = function () { var users = [ { id: 15, name: "Bob" }, { id: 23, name: "Jimbo" }, { id: 35, name: "Cathy" }, ]; users.forEach(function (u) { saveUser(u); }); };

forEach Exercise 2

Use forEach to calculate the volumes of each "box" in the boxes array and populate volumes with those figures. The volumes array should have 5 numbers in it.

var boxes = [ { length: 10, width: 15, height: 20 }, { length: 15, width: 20, height: 25 }, { length: 20, width: 25, height: 30 }, { length: 25, width: 30, height: 35 }, { length: 30, width: 35, height: 40 }, ]; var volumes = [];
Click to See Answer
var boxes = [ { length: 10, width: 15, height: 20 }, { length: 15, width: 20, height: 25 }, { length: 20, width: 25, height: 30 }, { length: 25, width: 30, height: 35 }, { length: 30, width: 35, height: 40 }, ]; var volumes = []; boxes.forEach(function (box) { volumes.push(box.length * box.width * box.height); });

^ There is actually a better way to do this! We'll learn about map next!

Complete and Continue