Lesson Monday

In the last lesson, we wrote our first Array.prototype.forEach() loop. In this lesson, we'll continue to practice this kind of loop. By the end of the lesson, you should have a basic understanding of how to write and apply an Array.prototype.forEach() loop. If you don't, we recommend reading the lesson again. Don't worry - you don't need to be a master of looping just yet. It's a complex enough concept that it can take time to master. Focus on having a growth mindset, be patient with yourself, and trust that it will make more sense with practice.

Let's start working with numbers instead of alerts. Our first example will just double numbers from an array and then log the doubled value to the console.

const array = [0,1,2,3,4,5];
array.forEach(function(number) { 
  console.log(number * 2);
});

In the example above, our loop calls the anonymous function six times - once for each element in the array. Try it out yourself.

Image shows the doubled values being logged to the console. The last line in the console states "undefined."

The first time through the loop, the callback (function(number) { console.log(number * 2); }) is executed on the first element in the array. The first element is 0. 0 * 2 is 0, which is logged to the console.

The second time through the loop, the callback is executed on the second element in the array. The second element is 1. 1 * 2 is 2, which is logged to the console.

And so on.

Note that in the image above, the last line in the console reads undefined. That's because the return value of an Array.prototype.forEach() loop is undefined.

By the way, it's really important to understand that the return of an Array.prototype.forEach() loop is undefined. We can't just store the results of Array.prototype.forEach() in a variable.

So what if we actually want to store the return values of each element in the array? This is a bit more involved. We need to create another variable to hold the doubled values. Then we can use the loop to put the doubled values in the array.

Here's how we can do it:

const array = [0,1,2,3,4,5];
let doubledArray = [];
array.forEach(function(element) {
  doubledArray.push(element * 2);
});
doubledArray;

We create an empty array where the doubled numbers will go. For clarity's sake, we name it doubledArray. Note that the original array is a const while doubledArray uses let. The original array is not altered. Instead, doubled values will be pushed into the new array.

Next, we loop through our original array. We've changed the parameter in the callback to element instead of number. You can call it whatever you wish - it's just a parameter. However, because a loop iterates through each element in an array, element is a common parameter to pass into a loop's callback.

Finally, we push the doubled value into doubledArray. Once the loop is finished, we can see that doubledArray contains all of the doubled elements.

If we want to modify all the elements in an array using this kind of loop, this is how to do it. We will learn another, cleaner way to do this when we learn about Array.prototype.map() in a future lesson.

Let's use a loop for a different kind of operation. This time, we will add all the elements in the array instead. Let's take a look:

const array = [0,1,2,3,4,5];
let sum = 0;
array.forEach(function(element) {
  sum += element;
});
sum;

Our original array remains a const. Our loop won't ever change it!

Next, we have a sum instead of a doubledArray. It's not an array - it's a number. Whenever we want to initialize a variable that adds things together, we'll usually start at 0.

We loop through each element in the array, calling sum += element;. This is shorthand for the following:

sum = sum + element;

Okay, this is another place where things can get really confusing for beginners. This looks like a math problem from algebra. If it were a math problem, element would have to be zero. There's no other way to make both sides of that equation work!

But this isn't a math problem here - it's computer programming. And yes, we are asking our little program to do math, which can compound the confusion. But this is what we are actually doing in the line above:

// This is pseudo-code!
newSum = oldSum + element;

We are telling JavaScript to take the value of our sum variable (called oldSum in our pseudo-code example) and add the value of element to it.

Here's how this looks each iteration through the loop:

This chart shows the changes each iteration through the loop.

In the table above, the first column denotes the number of times the loop has run. The second column is the value of sum when that iteration begins - what we called oldSum in our pseudocode. The third column shows what is being evaluated during that iteration of the loop. Finally, the last column shows the value of what we call newSum in our pseudocode - which is the value after the code in that iteration has run.

It may also help to study exactly what is happening in the console. Refresh your browser and then input the following code in the console:

const array = [0,1,2,3,4,5];
let sum = 0;
let oldSum;
let newSum;
array.forEach(function(numberToAdd) {
  debugger;
  oldSum = sum;
  sum = sum + numberToAdd;
  newSum = sum;
});

Note that we've added a debugger; statement to freeze execution just inside the loop. We've also renamed element to numberToAdd - and added oldSum and newSum variables. These variables are there so we can look at exactly what's happening. Run this code in the console by hitting Enter and then go to the Sources tab.

Before we step through our code, we are going to make sure we're watching our new variables. Let's add a new tool to our Chrome DevTools repertoire:

We can watch variables by adding them in the _Watch_ tab in _Sources.

In the right-hand pane, we can click Watch to add variables we want to watch the values of. Note that these values are also available in the Scope section in the same pane. The benefit of Watch is that we can manually make sure we are watching the value of variables as they come in and out of scope. You should take advantage of both of these features when you are debugging!

Next, we can step through our code by clicking the blue arrow. When our code is executed, each time the debugger; statement is reached, the code will pause. That means the code will pause six times in all - once for each iteration through the loop. Take a look at how the values change with each iteration.

Step through the code to see how the variables change.

While the GIF above can be helpful, take the time to step through the function in the console at your own pace - and run the function a few times in the console, stepping through it each time, to make sure you are clear on what's happening. Note that you'll need to refresh the browser before you run the function again - that way, you'll clear let and const variables so they can be declared anew again. Otherwise, you'll get Uncaught SyntaxError: Identifier has already been declared.

As we can see, Array.prototype.forEach() is extremely powerful. We can use it for so many different things. We will run through a few more quick examples. Try them out in the console!

let thingsILike = "I like...";
const arrayOfThingsILike = ["bubble baths", "kittens", "good books", "clean code"];
arrayOfThingsILike.forEach(function(thing) {
  thingsILike = thingsILike.concat(" " + thing + "!");
});
thingsILike;

A few things to note here:

  • We are adding on to a string, not a number. That means thingsILike is a string. Often, we will initialize with an empty string "", but in this case, we have a string we want to start with.
  • We concatenate the current element of the array (which we call thing) to the thingsILike string. Because `String.prototype.concat() is not a destructive method, we have to save it in a variable.

We can also use loops to run jQuery code and modify the DOM. Here's a hypothetical example of the things I like example. (The example is hypothetical because we aren't providing the HTML code to make this example work.)

const arrayOfThingsILike = ["bubble baths", "kittens", "good books", "clean code"];
arrayOfThingsILike.forEach(function(thing) {
  $("#likable-things").append(" " + thing + "!")
});

Here, we are looping through the same array from the arrayOfThingsILike example above. The key difference is that each time through the loop we are appending a string to a thing in the DOM with an id of #likable-things. As a result, we don't need to worry about storing likable things in a variable.

We are really just scratching the surface here. There is so much you can - and will - do with loops. At this point, hopefully things are getting a bit clearer. If not, don't panic. Start by rereading the lesson. If things still aren't fully clear, stick with the growth mindset attitude and trust your learning process.

Examples


Logging values to the console:

const array = [0,1,2,3,4,5];
array.forEach(function(number) { 
  console.log(number * 2);
});

Creating a New Array with Modified Elements

const array = [0,1,2,3,4,5];
let doubledArray = [];
array.forEach(function(element) {
  doubledArray.push(element * 2);
});

Using a Loop to Sum

const array = [0,1,2,3,4,5];
let sum = 0;
array.forEach(function(element) {
  sum += element;
});

Using a Loop to Make a String

let thingsILike = "I like...";
const arrayOfThingsILike = ["bubble baths", "kittens", "good books", "clean code"];
arrayOfThingsILike.forEach(function(thing) {
  thingsILike = thingsILike.concat(" " + thing + "!");
});

Using A Loop to Add Elements to the DOM

const arrayOfThingsILike = ["bubble baths", "kittens", "good books", "clean code"];
arrayOfThingsILike.forEach(function(thing) {
  $("#likable-things").append(" " + thing + "!")
});

Lesson 12 of 31
Last updated June 22, 2020