Why can't you break out of the forEach loop?
Tags: javascript, react, webdev, vue
Published: 2021-09-29 16:26:09

This is one of the many things I keep forgetting every now and then. Other things like taking out clothes from the washing machine, watering my plants, okay but this post is not about me being forgetful. I am sure lot many of you reading this post do know this but still its not until you try to break out of the "***forEach***" loop that you realize you made the same mistake once again. This post is just a reminder for most of us and maybe a short clarification for the rest of us.

![Forgetful](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5foi98ggws96c1vi2rzs.jpg)

Moving ahead with an example because examples are the quickest way to explain stuff. Lets say we have ***an array of flowers*** and we want to collect all the flowers unto my favorite "***Tulip***" starting from the first one. Yes, please dont make it complicated by throwing in scenarios like what if there are multiple "***Tulips***". We have an array of flowers, where ***each flower appears once*** like so:

{% runkit %}
const flowers = ["Rose", "Lily", "Marigold", "Jasmine", "Tulip", "Lotus", "Orchid", "Daffodil", "Sunflower", "Poppy"];
{% endrunkit %}<br>

How would you do it? If I were you I'd rush to get the "***forEach***" loop down first but not this time. Lets use the ***conventional for loop*** and get this done first. Silly but helpful. Easy said, easy done! Then we shall also try that out with my favorite "***forEach***" loop. Take a look at the following snippets.

{% runkit %}
const flowers = ["Rose", "Lily", "Marigold", "Jasmine", "Tulip", "Lotus", "Orchid", "Daffodil", "Sunflower", "Poppy"];

let vase = [];
//collect all flowers unto "Tulip"
for(let i=0; i < flowers.length; i++) {
  vase.push(flowers[i]);
  if(flowers[i]==="Tulip") break;
}
console.log(vase); // ["Rose","Lily","Marigold","Jasmine","Tulip"]
{% endrunkit %}<br>

{% runkit %}
const flowers = ["Rose", "Lily", "Marigold", "Jasmine", "Tulip", "Lotus", "Orchid", "Daffodil", "Sunflower", "Poppy"];

let vase = [];
//collect all flowers unto "Tulip"
flowers.forEach(flower => {
  vase.push(flower);
  if(flower==="Tulip") {
    break; //Illegal break statement
  }
});
{% endrunkit %}<br>

Had you tried that on your own, you'd have come across this error that says "***Illegal break statement***". You can't break out of the forEach loop after you're done collecting "***Tulip***". You may have already figured out but don't worry if you haven't and let me tell you how does the forEach loop differ from all the conventional loops. "***forEach***" more than being a loop, is a function call and you know it right from the syntax. This function takes another ***callback function*** and mind it, the callback function has to be a ***synchronous*** function. The synchronous callback function essentially is then called in interation on the array on which you did call the "***forEach***" loop. I understand, that this may not sound very intuitive. So, let me try explaining this with a demo polyfill of the "***forEach***" function. You can easily make it go crazy throwing errors but for a quick example, it should suffice. For complete implementation you can [see this](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach#polyfill).

{% runkit %}
// forEach polyfill
Array.prototype.customForEach = function(callback) {
  const arr = this;
  // internal loop
  for(let i=0; i<arr.length; i++) {
    const x = arr[i];
    callback.call(arr, x);
    // only if we could add a break here, but we can't reach this place
  }
}

const callback = function(x) {
  console.log(x);
  // break; // Illegal break statement
}

// using custom forEach
const flowers = ["Rose", "Lily", "Marigold", "Jasmine", "Tulip", "Lotus", "Orchid", "Daffodil", "Sunflower", "Poppy"];
flowers.customForEach(callback);
{% endrunkit %}<br>

Now when you look at the ***poyfill*** (customForEach), you'll be able to comprehend the situation much clear. You'd also agree how placing a "***break***" statement inside a function (named callback) is inappropriate. [Read what MDN docs say](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/break#:~:text=A%20break%20statement%2C%20with%20or%20without%20a%20following%20label%2C%20cannot%20be%20used%20within%20the%20body%20of%20a%20function%20that%20is%20itself%20nested%20within%20the%20current%20loop%2C%20switch%2C%20or%20label%20statement%20that%20the%20break%20statement%20is%20intended%20to%20break%20out%20of.). Even if you assumed that something like a "***break***" statement was valid inside a function (which indeed isn't the case), you'd see that it would not be able to break out of the loop, since there's no way you can add a "***break***" statement inside the internal loop. Why? because ***you simply cannot access it from outside***.

Accomplishing the task we took as an example here for this post, is not a tough job. There are numerous ways this can be done but apart from this example, for your use-case checkout the [alternatives available](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach#:~:text=There%20is%20no%20way%20to%20stop%20or%20break%20a%20forEach()%20loop%20other%20than%20by%20throwing%20an%20exception.%20If%20you%20need%20such%20behavior%2C%20the%20forEach()%20method%20is%20the%20wrong%20tool) at your disposal. Again, this is not an exhasutive list but then the purpose of this post is served and anything beyond this would only stretch the content unnecessarily I believe. Also since I have now written this post, I think I won't repeat this mistake ***or will I***?

![Do not forget](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eq7ifmuwg796quwqk7hi.png)

<br><hr>
##Originally Posted Here -
https://mayankav.webflow.io/blog/you-cant-break-the-foreach-loop