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):
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 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 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!
Top comments (0)