Can you break out of a “forEach” loop in JavaScript?
It’s an amazing question to challenge just how well you really know JavaScript.
Because we’re not talking for loops — or this would have been ridiculously easy: you just break
:
But you wouldn’t dare do this with forEach
, or disaster happens:
What about return… mhmm.
What do you think is going to happen here:
return
should easily end the loop at 5
and take us to the outer log
right?
Wrong:
Remember: forEach takes a callback and calls it FOR EACH item in the array.
// Something like this:
Array.prototype.forEach = function (callback, thisCtx) {
const length = this.length;
let i = 0;
while (i < length) {
// 👇 callback run once and only once
callback.call(thisCtx, this[i], i, this);
i++;
}
};
So return
only ends the current callback call and iteration; doing absolutely nothing to stop the overall loop.
It’s like here; trying to end func2()
from func1()
— obviously not going to work:
5 terrible ways to stop a forEach loop
1. Throw an exception
You can stop any forEach loop by throwing an exception:
const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
try {
nums.forEach((num) => {
if (num === 5) {
throw new Error('just to stop a loop?');
}
console.log(num);
});
} catch {
console.log('finally stopped!');
}
Of course we’re just having fun here — this would be horrible to see in real-world code. We only create exceptions for problems, not planned code like this.
2. process.exit()
This one is extreme:
const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
nums.forEach((num) => {
if (num === 5) {
process.exit(0);
}
console.log(num);
});
Not only are you ending the loop, you’re ending the entire program!
You won’t even get to the console.log()
here:
3. Array
some()
This is bad.
It works and some people recommended it for this; but this lowers readability as it’s clearly not what it’s meant for.
This is what it’s meant for:
const nums = ['bc', 'bz', 'ab', 'bd'];
const hasStartingA = nums.some((num) =>
num.startsWith('a')
);
const hasStartingP = nums.some((num) =>
num.startsWith('p')
);
console.log(hasStartingA); // true
console.log(hasStartingP); // false
4. Set array length to 0
But here’s something even more daring: Setting the length of the array to 0!
const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
function myFunc() {
nums.forEach((num) => {
if (num === 5) {
nums.length = 0;
}
console.log(num);
});
console.log('it worked!');
console.log(nums);
}
myFunc();
Setting the array’s length completely destroys and resets it — EMPTY array:
5. Use Array
splice()
Things get even weirder when you use Array
splice()
to stop the foreach loop, deleting slashing away elements mid-way!
const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
function myFunc() {
nums.forEach((num, i) => {
if (num === 5) {
nums.splice(i + 1, nums.length - i);
}
console.log(num);
});
console.log('spliced away!');
console.log(nums);
}
myFunc();
3 great ways to stop a loop
1. Do you really need to break?
Instead of using the terrible methods above to stop a forEach loop…
Why not refactor your code so you don’t need to break at all?
So, instead of this:
const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
try {
nums.forEach((num) => {
if (num === 5) { // ❌ break at 5
throw new Error('just to stop a loop?');
}
console.log(num);
});
} catch {
console.log('finally stopped!');
}
We could have simply done this:
const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
nums.forEach((num) => {
if (num < 5) { // ignore 5 or more
console.log(num);
}
});
console.log('no need to break!');
2. Use for of
But if you really want to jump out of the loop early then you’re much better of with the for..of
loop:
const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
try {
for (const num of nums) {
if (num === 5) {
break; // 👈 break works
}
console.log(num);
}
} catch {
console.log('finally stopped!');
}
3. Use traditional for
Or with the traditional for
loop, for more fine-grained control:
const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
try {
for (let i = 0; i < nums.length; i += 2) { // 👈 jump by 2
const num = nums[i];
if (num === 5) {
break;
}
console.log(num);
}
} catch {
console.log('finally stopped!');
}
Final thoughts
So there are ways to “break” from a forEach loop, but they’re pretty messy and insane.
Instead try refactoring the code to avoid needing to break in the first place. Or switch to for
and for..of
for a cleaner, readable approach.