# Introduction To Array For Each

## Objectives

1. Explain why we use `.forEach()`.
2. Explain how `.forEach()` works.

## The weaknesses of `for` loops

Up until now, we've been doing our iterating with `for` loops. These are great for one-off tasks, and they're reasonably explicit: "I'm incrementing a variable, `i`, from `0` to `myArray.length - 1` and using `i` to access the elements of the array."

``````var evens = [0, 2, 4, 6, 8, 10];

for (var i = 0; i < evens.length; i++) {
console.log(`\${evens[i]} is not odd!`);
}
``````

But wouldn't it be nice if there were a way to access the elements directly, without having to type out `evens[i]`?

Well, it's our lucky day!

Follow along in `index.js` — you can run your code by copying it into your browser's console.

## `.forEach()`

Every array in JavaScript comes with the `.forEach()` method.

This method lets us iterate over every element of the array directly, without writing out a whole `for` loop. Let's rewrite the above example using `.forEach()`:

``````var evens = [0, 2, 4, 6, 8, 10];

evens.forEach(even => {
console.log(`\${even} is not odd!`);
});
``````

Whoa! It's so much shorter! Even though this is just a tiny piece of code, let's make sure we understand what's happening.

On the array `evens` we invoke the method `.forEach()` by typing `evens.forEach()`. The `.` tells JavaScript that we're going to access some property of the `evens` array. This property, `forEach`, happens to be a function, which, as we know, we invoke with parentheses around its arguments. `.forEach()` requires one argument, a function.

Whaaaaat? Did we read that right? We can pass a function as an argument? You bet your boots we can! In the above example, we pass an ES6 arrow function as the argument to `evens.forEach()`:

``````even => {
console.log(`\${even} is not odd!`);
}
``````

The function passed to `.forEach()` accepts up to three arguments: the current element in the array upon which `.forEach()` was called, the index of that element in the array, and the array itself.

Let's add a second (`index`) and third (`array`) parameter to the function and step through it with the debugger to get a feel for all three arguments.

``````var evens = [0, 2, 4, 6, 8, 10];

evens.forEach((even, index, array) => {
debugger;
console.log(`\${even} is not odd!`);
});
``````

As a reminder, `debugger` is globally available and opens up the debug console in your browser when it's evaluated. Clicking the arrow () or pressing the `F10` key will let you step through the function calls and inspect the three arguments that `.forEach()` passes to the function as it iterates over the `evens` array. On each pass through the `.forEach()` loop, the `even`, `index`, and `array` variables contain the following values:

Pass # `even` `index` `array`
1 0 0 [0, 2, 4, 6, 8, 10]
2 2 1 [0, 2, 4, 6, 8, 10]
3 4 2 [0, 2, 4, 6, 8, 10]
4 6 3 [0, 2, 4, 6, 8, 10]
5 8 4 [0, 2, 4, 6, 8, 10]
6 10 5 [0, 2, 4, 6, 8, 10]

It's possible to provide the same functionality with a regular `for` loop, but to do so we would have to jump through some hoops that `.forEach()` mercifully abstracts away for us. To replicate `.forEach()` with a `for` loop, we could define the function ahead of time and then invoke it inside of the loop...

``````var evens = [0, 2, 4, 6, 8, 10];

function evenFn(even, index, array) {
console.log(`\${even} is not odd!`);
}

for (let i = 0; i < evens.length; i++) {
evenFn(evens[i], i, evens);
}
``````

...but that seems like too many extra lines for such a simple operation. `.forEach()` provides a wonderfully compact, readable syntax for invoking a function on every member of an array. It's a powerful tool that makes it easier for us to perform complex operations in just a few lines of code.

## Functions as Arguments

Functions in JavaScript are first-class objects, which means we can treat them just as we would numbers, strings, arrays, and other JavaScript objects. Functions "can be stored in variables, passed as arguments to functions, created within functions and returned from functions." Often, we will pass a function as an argument to another function so that it can serve as a callback, a very powerful concept in functional programming. Essentially, the main function (`mainFn()`) that receives the callback function (`callbackFn()`) as an argument will invoke the passed-in `callbackFn()` at some later point, perhaps waiting until other processes have completed or until data that the `callbackFn()` relies upon becomes available.

Callbacks are a very important concept that you'll employ throughout your JavaScript career. The basic idea is that we define a function but delegate control of when it should be invoked to another function.

For example, take the following function, `square()`, which multiplies the passed-in number by itself and logs out the result:

``````function square(n) {
console.log(n * n)
}
``````

If we just wanted to square all of the elements in `evens`, we could write `evens.forEach(square)`.

But what if we don't know ahead of time what we want to do to the elements in our `evens` array? We can make our little program even more generic by wrapping it all up in a function that accepts another function (a callback) as an argument:

``````var evens = [0, 2, 4, 6, 8, 10];

function doToEvens(callback) {
evens.forEach(callback);
}
``````

Now we can pass any function to `doToEvens` and that function will be invoked on every element of the `evens` array!

Let's take it a step farther — what if we don't know beforehand which array we're going to be operating on? We can define a function that accepts two arguments: an array and a callback function to pass to `.forEach()`:

``````function doToElementsInArray(array, callback) {
array.forEach(callback);
}
``````

Our code is short and sweet, but it's also generic and enormously powerful.

``````function changeCompletely(element, index, array) {
array[index] = Math.floor(Math.random() * 100 + 2).toString() + ` \${array[index]}s!!!`;
}

var animals = ["dog", "cat", "squirrel"];

doToElementsInArray(animals, changeCompletely);

// log out animals -- pretty cool, right?
console.log(animals);
``````

If you've been following along in `index.js`, you should now be able to run `learn` — all of the tests should pass!

Learn to code.