JavaScript Arrays: .forEach - The Functional for of loop
Tags: javascript, arrays, functional, foreach
Published: 2019-05-14 20:30:54

Meet `Array​.prototype​.for​Each()`.  
It's purpose is to execute the code you provide it over each item of the array: essentially a **loop**.

Here's its definition:

```js
array.forEach(function callback(currentValue [, index [, array]]) {  
// code for this iteration  
}[, thisArg]);  
```

Let's explain it below. 😉

# It's Parameters  

`forEach` accepts up to two parameters:  

- the `callback` function, which is executed over each item of the array  
- the `thisArg` (optional), which changes the value of `this` inside of the callback function

Now, a deeper look at each one. 👇

  
## 1) The `callback` function

The method that is called on each element of the array. It takes up to three parameters:  

  
- currentValue: current item of the array, `🍎` on the first iteration  
- index (optional): index of the current item, `0` on the first iteration  
- array (optional): the whole array, the `same` on all iterations

  
```js
const array = ["🍎", "🍌", "🍍"];

array.forEach(function(current, index, array) {  
console.log(current);  
console.log(index);  
console.log(array);  
console.log("\n");  
});

// LOGS  
// { current: '🍎' }  
// { index: 0 }  
// { array: [ '🍎', '🍌', '🍍' ] }  
//  
// { current: '🍌' }  
// { index: 1 }  
// { array: [ '🍎', '🍌', '🍍' ] }  
//  
// { current: '🍍' }  
// { index: 2 }  
// { array: [ '🍎', '🍌', '🍍' ] }  
```

### The `index` Parameter

The `index` parameter is optional. It is handy when the logic depends on the item's position in the array.

```js
const fruitEmojis = ["🍎", "🍌", "🍍"];  
const fruitNames = ["apple", "banana", "pineapple"];

fruitEmojis.forEach(function logFruitName(currentFruitEmoji, index) {  
const fruitName = fruitNames[index];

console.log({ emoji: currentFruitEmoji, name: fruitName });  
});

// LOGS  
// { emoji: '🍎', name: 'apple' }  
// { emoji: '🍌', name: 'banana' }  
// { emoji: '🍍', name: 'pineapple' }  
```

###  The `array` Parameter

The last parameter is `array`. It is the value of the whole array at the beginning of the execution of the callback method.
**Handy**: It is useful when you have a generic method that you pass to `forEach` which requires access to the array.  
The method being generic you cannot know in advance the array it will be called on. Which also mean you cannot rely on the closure as it is unknown.  
Thus the `array` parameter in that case is your **only** option to get access to the current array.  

See this Stackoverflow response [reply](https://stackoverflow.com/a/39528692) from [redneb](https://stackoverflow.com/users/6776093/redneb) for more info.

  
## 2) The `thisArg` Parameter

Overrides the `this` keyword value inside the `callback` function.  
By default `this` would refer to the window object, and it will be overridden by the value you pass it.

```js
const array = [1];

array.forEach(function basicCall(current) {  
console.log(this);  
});

// LOGS  
// ... the whole Window object actually (in the browser)

const thisArg = { context: "custom" };

array.forEach(function explicitThisArg(current) {  
console.log(this);  
}, thisArg);

// LOGS  
//`{context: "custom"}`, which is the custom `this` value passed  
```

  
# My Usage of `forEach`

I generally use it when I want to apply a side-effect to some object or another array. (I try avoiding side-effect as much I can.)

## Example

In this case we have a list of emojis and the corresponding list of names. We want to create an object where the key will be the name and the value will contain the emoji.

The two arrays are sorted the same way: at any given index items from both array correspond.

```js
const fruitEmojis = ["🍎", "🍌", "🍍"];  
const fruitNames = ["apple", "banana", "pineapple"];

let fruitMap = {};

fruitEmojis.forEach(function addKeyPairToFruitMap(currentFruitEmoji, index) {  
const key = fruitNames[index];

fruitMap[key] = currentFruitEmoji;  
});

console.log(fruitMap);

// LOGS  
// { apple: "🍎", banana: "🍌", pineapple: "🍍" }  
```

Note that `fruitMap` is created before calling forEach on `fruitEmojis`. And we update the object during the executions of `addKeyPairToFruitMap`.

  
# Information To Consider  
Before using the `forEach` methods on arrays here's some information worth knowing.

## 1) Returns `undefined`, thus NOT Chainable

The `forEach` array method always returns `undefined`, thus it is **NOT** chainable. Which means that in a *call chain*, it can only be placed at the **end**.

```js
const fruitEmojis = ["🍎", "🍌", "🍍"];

let fruitMap = {};

fruitEmojis  
.forEach(function addKeyPairToFruitMap(currentFruitEmoji) {  
return currentFruitEmoji;  
})  
.map(function logEmoji(emoji) {  
console.log("Calling `.map` will throw an error!");  
}  
);

// LOGS (console.error)  
// ... (omitted details)  
// .map(function logEmoji(emoji) {  
// ^  
// TypeError: Cannot read property 'map' of undefined  
// ... (omitted details)  
```

  
## 2) Callback Function Can Modify Original Array  
We can add/remove/update items from the array from inside the callback function.

### Addition  
Adding does **NOT** affect the items for the call: only the items initially present are processed.  
But after the execution we see that it was affected.  
```js
const fruitEmojis = ["🍎", "🍌", "🍍"];

let fruitMap = {};

fruitEmojis.forEach(function addKeyPairToFruitMap(currentFruitEmoji, index) {  
fruitEmojis.push(`test ${index}`);

console.log({index});  
});

console.log({fruitEmojis});

// LOGS

// `forEach`:  
// { index: 0 }  
// { index: 1 }  
// { index: 2 }

// logging the array:  
// { fruitEmojis: [ '🍎', '🍌', '🍍', 'test 0', 'test 1', 'test 2' ] }  
```

### Deletion  
Deletion **DOES** affect the number of items for the call. If the next planned item is removed it will not be processed.

```js
let fruitEmojis = ["🍎", "🍌", "🍍"];

let fruitMap = {};

fruitEmojis.forEach(function addKeyPairToFruitMap(currentFruitEmoji, index) {  
fruitEmojis.shift();  
fruitEmojis.pop();  
fruitEmojis.splice(0, 1);

console.log({index});  
});

console.log({fruitEmojis});

// LOGS

// `forEach`:  
// { index: 0 }

// logging the array:  
// { fruitEmojis: [] }  
```

### Modification  
Modification **DOES** affect the items **themselves** for the call, but not the count. If we modify the next planned item, this modification is available when it is then processed.  
Note that the forth item is due to this statement the following statement which adds an item to the array on the last execution: `fruitEmojis[index + 1] = "AAAAAARH!";`. 

```js
let fruitEmojis = ["🍎", "🍌", "🍍"];

let fruitMap = {};

fruitEmojis.forEach(function addKeyPairToFruitMap(currentFruitEmoji, index) {  
fruitEmojis[index + 1] = "AAAAAARH!";  
  
console.log({currentFruitEmoji, index});  
});

console.log({fruitEmojis});

// LOGS

// `forEach`:  
// { currentFruitEmoji: '🍎', index: 0 }  
// { currentFruitEmoji: 'AAAAAARH!', index: 1 }  
// { currentFruitEmoji: 'AAAAAARH!', index: 2 }

// the array  
// { fruitEmojis: [ '🍎', 'AAAAAARH!', 'AAAAAARH!', 'AAAAAARH!' ] }  
```

## 3) Cannot Be Stopped  
You cannot stop the execution or "break the loop" when calling the forEach method.

If you are trying to stop the execution you should probably use a different array method (eg. find, filter, reduce, some, includes) or use a **for-loop** instead.

# Conclusion  
I hope this article about the `forEach` method has brought you value. 🙂  
It will be part of a series on JavaScript arrays, so stay tuned for the next one! 🎉  
Until then, happy coding! 😎