📓 1.3.3.6 When to use for
In this lesson, we'll compare use cases for Array.prototype.forEach()
and for
loops. As we'll learn, we'll favor using a for
loop when we're not iterating over an array, and if we need to break out of an array and not loop over every value in it. As we move through the examples in this lesson, put them into the DevTools console to try them out.
When to Use for
Loops
In general, we should use Array.prototype.forEach()
when we want to loop through every element in an array. If we are using a loop that isn't iterating through an array, we can't use Array.prototype.forEach()
for that loop — that's pretty obvious.
However, sometimes we can't use Array.prototype.forEach()
when we are looping through an array. Specifically, if we want to stop the loop, we can't use Array.prototype.forEach()
. Looping through every element in an array is a requirement of Array.prototype.forEach()
.
Let's look at an example when this might matter. Let's say we have a series of arrays that hold sequences of DNA. These sequences can potentially be very long — and we want to stop searching an array as soon as we find a pattern. We'll call that pattern "A" (to represent a specific DNA sequence). We'll also add a few other letters to represent other DNA sequences. A biologist won't be impressed by our approximation... but we are programmers and this is a programming example!
Here's our sample "sequence":
const dnaSequence = ["X", "A", "Y", "M", "D"];
In this example, "A"
is the second element in this array. We could use an Array.prototype.forEach()
loop to flag the sequence if it includes "A"
. Here's the code:
> let dnaFlag = false;
> const dnaSequence = ["X", "A", "Y", "M", "D"];
> dnaSequence.forEach(function(element) {
if (element === "A") {
dnaFlag = true;
};
console.log("Looped!")
});
> dnaFlag;
Looped!
Looped!
Looped!
Looped!
Looped!
true
In the code above, when an iteration through the loop finds a match with "A"
, it will switch the dnaFlag
boolean to true
. Using boolean flags in this manner is very common in coding.
Note, however, that the second character in our array matched the letter "A"
. What if our array were a million elements long? (DNA sequences can be very complex.) Our loop needs to loop through all million elements — even though we really only need to do two iterations of the loop to switch dnaFlag
to true
. This would be horribly inefficient. We've added a console.log("Looped!")
to show how many times this loop runs.
In order to break out of loop, we need to use the break;
keyword. This keyword does exactly what it sounds like: stops a loop.
What happens if we try to add a break;
statement to the loop above?
> let dnaFlag = false;
> const dnaSequence = ["X", "A", "Y", "M", "D"];
> dnaSequence.forEach(function(element) {
if (element === "A") {
dnaFlag = true;
break;
};
});
> dnaFlag;
Uncaught SyntaxError: Illegal break statement
We'll get the following error: Uncaught SyntaxError: Illegal break statement
. In short, we can't break out of this kind of loop.
However, we can use a break statement with a for
loop. Try the following in the console:
> let dnaFlag = false;
> const dnaSequence = ["X", "A", "Y", "M", "D"];
> for (let i = 0; i < dnaSequence.length; i +=1) {
if (dnaSequence[i] === "A") {
dnaFlag = true;
break;
};
console.log("Looped!");
}
> dnaFlag;
Looped!
true
We've added a console.log("Looped!")
to this code, too — and you'll see it only triggers once. The second time through the loop, the condition is met and the loop breaks due to the break;
keyword.
There's something that's not so great about the code above. As of now, the dnaFlag
variable is globally scoped. In an ideal world, we'd wrap this all in a function. Let's do this now, not just because it's better code but also so we can see what happens when we try to return
out of both a for
loop and an Array.prototype.forEach()
loop.
We'll start by wrapping the for
loop in a function called dnaPatternDetector
:
> function dnaPatternDetector(dnaSequence, pattern) {
for (let i = 0; i < dnaSequence.length; i +=1) {
if (dnaSequence[i] === pattern) {
return true;
};
console.log("Looped!");
}
return false;
}
We've done a bunch of things to refactor this code. Our function takes two parameters. The dnaSequence
is an array of characters. The pattern is the character we are looking for (we are looking for "A"
).
We actually don't need to use the dnaFlag
anymore. If the pattern is met (dnaSequence[i] === pattern
), then the loop will stop running and our function will return true
. If the pattern is never met, our loop will complete and the final part of our function will be reached: return false;
.
Let's try the following out in the DevTools console. First, some variables — a sequence
variable that includes an array and two variables for patterns: pattern1
and pattern2
:
> const sequence = ["X", "A", "Y", "M", "D"];
> const pattern1 = "A";
> const pattern2 = "Z";
Next, we'll also need to add our dnaPatternDetector()
function in the console as well.
Finally, try this out:
> dnaPatternDetector(sequence, pattern1);
Looped!
true
We'll see that the function returns true
— exactly what we'd expect because sequence
includes "A"
. We also see that it only hits the console.log("Looped!")
statement once. return
has the same effect as the break;
statement here — however, it doesn't just break us out of the loop, it returns from the function.
Now try out the second pattern, which is a character that's not included in sequence
:
> dnaPatternDetector(sequence, pattern2);
Looped!
Looped!
Looped!
Looped!
Looped!
false
Our loop iterates through every character in the array and never finds the character "Z"
. The loop completes (so "Looped!" is printed to the screen five times). This is the only way the final part of the code can be reached: return false
. The function returns false.
A function that actually checks DNA sequences would probably be quite a bit more complicated than this example. However, this does show a potential use case for when we'd want to break out of a loop — either with a break;
or a return
statement. This same function wouldn't work as intended with an Array.prototype.forEach()
loop — if we try to put a return
statement inside the loop, we'll get an error. The rules for Array.prototype.forEach()
loops are strict — we must iterate through every element in the array — we can't break or return from it.
To summarize, you should favor Array.prototype.forEach()
loops over for
loops except in the following cases:
- You're not looping through an array.
Array.prototype.forEach()
can only be used with arrays. - You need to break out of the loop — either with
break;
or areturn
statement.
We can add one more case just for the sake of practice:
- You should favor
for
loops to loop through every element in an array until you understand exactly how they work. They are a cornerstone of JavaScript and it's essential to understand them even if you'll mostly use other types of loops in the future.
In the next lesson, we'll make changes to our text analyzer application. Both will be situations where a for
loop will serve our purposes better.
You can use any kind of loop you want for this section's independent project. The project prompt can be solved with Array.prototype.forEach()
but you are welcome to use for
(or another kind of loop you learn later in this section) as well.