You can actually stop a "forEach" loop in JavaScript - in 5 ways

Last updated on April 18, 2024
You can actually stop a "forEach" loop in JavaScript - in 5 ways

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.

See also