forEach for Dummies!
Published: 2024-06-05 10:06:10

It's happened to all beginner developers. We learn a new concept, familiarize ourselves with new functionality in a limited, controlled context and then—much to our frustration—find that in the real world, its application is more nuanced and complex than we anticipated. For someone like me who tends to lean on intuition, this can be incredibly frustrating. Intuition is a double-edged sword when it comes to learning code.

While my hunches are often right, they are just as easily proven wrong. My preconceived notion of what my code might do is often upended by the smallest detail that my intuition deemed irrelevant. And one great example of this is my recent experience with `forEach()`. First, let's review how it works:

## `forEach()` Overview
`forEach()` is an array iterator, one of six available JavaScript methods for array iteration including `map()`, `filter()`, `reduce()`, the `for` loop, and the `for...of` loop.

`forEach()`, simply put, allows you to iterate through each element of an array and perform an action on that element in the form of a function. Here's a simple example of what that looks like in action ([taken from MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach)):

```
const array1 = ['a', 'b', 'c'];

array1.forEach((element) => console.log(element));

// Expected output: "a"
// Expected output: "b"
// Expected output: "c"
```

While `for` loops can accomplish the same purpose, they require [more detailed syntax](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for) to execute. 

```
let str = '';

for (let i = 0; i < 9; i++) {
  str = str + i;
}

console.log(str);
// Expected output: "012345678"
```

`forEach()` is a simpler way to iterate through items of an array, and is often presented as a parallel method that might be stylistically preferred by certain programmers. However, there are some key differences between a `for` loop and the `forEach()` method that, had I known, would have saved me hours of debugging to no avail. 

## How I tripped up on `forEach()`

The task was relatively simple. Given an array of objects, which each object representing a player, and each player object containing keys with stats for that player, I needed to write a function that would iterate through the array, find a player whose name matches the name passed to the function as an argument, and return the number of points that player has scored.

The problem? I had written a function that seemed to be a straightforward  solution: 

```
function numPointsScored(name){
  const teamKeys = Object.keys(gameObject());
  forEach(teamKey => {
      const players = gameObject()[teamKey].players
      const playerNames = Object.keys(players)
      for(const playerName of playerNames){
        if (playerName === name) {
          return players[playerName].points
        }
      }
  })
}
```

However, testing this function with any name would simply return "undefined." I ran debuggers in different parts of the code, checked all the variables, everything seemed to be working correctly and yet still, I couldn't get the number of points that we expected. I ran through this with my instructor and we still couldn't figure out what was happening. After nearly an hour, we decided to walk away from it.

Later on, my instructor found that replacing `forEach()` with a simple `for` loop seemed to solve the problem:

```
function numPointsScored(name){
    const teamKeys = Object.keys(gameObject());
    for(const teamKey of teamKeys) {
        const players = gameObject()[teamKey].players
        const playerNames = Object.keys(players)
        for(const playerName of playerNames){
          if (playerName === name) {
            return players[playerName].points
          }
        }
    }
  }
```

While finding this solution was a relief, I felt equally exasperated and frustrated. How could the solution be so simple, and WHY was this the case if the functionality of `forEach()` and `for` loops are the same? 

The answer is—of course—they aren't!

## Limitations of `forEach()`

There are several limitations to using `forEach()`, and I'd definitely recommend [checking out this blog](https://dev.to/jeffsalive/think-twice-before-you-use-the-foreach-array-method-2i0a) for more great instances of how `forEach()`'s limitations actually make it a method many developers choose to avoid.

The key problem that I encountered with `forEach()` is that **you can't break it** by asking it to perform an action on a specific element and then break the loop. With `forEach()`, committing to iterating over the _entire array_. 

There are other issues with this method, such as that it may be less performant than a `for` loop for large arrays, and is less than ideal for asynchronous tasks. 

The moral of this story is, when using array methods, make sure you're aware of their limitations. It could save you a huge headache and hours of debugging!