let
firstPrime
=
null
;
for
(
let
n
of
bigArrayOfNumbers
) {
if
(
isPrime
(
n
)
&&
firstPrime
===
null
)
firstPrime
=
n
;
}
If
bigArrayOfNumbers
has a million numbers, and only the last one is prime (unbe‐
knownst to you), this approach would be fine. But what if the first one were prime?
Or the fifth, or the fiftieth? You would be checking to see if a million numbers are
prime when you could have stopped early! Sounds exhausting. We can use a
break
statement stop as soon as we’ve found what we’re looking for:
let
firstPrime
=
null
;
for
(
let
n
of
bigArrayOfNumbers
) {
if
(
isPrime
(
n
)) {
firstPrime
=
n
;
break
;
}
}
If this loop is inside a function, we could use a
return
statement instead of
break
.
Using Value of Index After Loop Completion
Occasionally, the important output of a loop is the value of the index variable when
the loop terminates early with a
break
. We can take advantage of the fact that when a
for
loop finishes, the index variable retains its value. If you employ this pattern, keep
in mind the edge case where the loop completes successfully without a
break
. For
example, we can use this pattern to find the index of the first prime number in our
array:
let
i
=
0
;
for
(;
i
<
bigArrayOfNumbers
.
length
;
i
++
) {
if
(
isPrime
(
bigArrayOfNumbers
[
i
]))
break
;
}
if
(
i
===
bigArrayOfNumbers
.
length
)
console
.
log
(
'No prime numbers!'
);
else
console.log(
`First prime number found at position
${
i
}
`
);
Using Descending Indexes When Modifying Lists
Modifying a list while you’re looping over the elements of the list can be tricky,
because by modifying the list, you could be modifying the loop termination condi‐
tions. At best, the output won’t be what you expect; at worst, you could end up with
an infinite loop. One common way to deal with this is to use descending indexes to
start at the end of the loop and work your way toward the beginning. In this way, if
you add or remove elements from the list, it won’t affect the termination conditions
of the loop.
Useful Control Flow Patterns | 77