249

I tried this:

for(i = 0; i < 5; i++){
    for(j = i + 1; j < 5; j++){
        break(2);
    }
    alert(1);
}

only to get:

SyntaxError: missing ; before statement

So, how would I break a nested loop in JavaScript?

Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
Mask
  • 33,129
  • 48
  • 101
  • 125

14 Answers14

660

You should be able to break to a label, like so:

function foo () {
    dance:
    for (var k = 0; k < 4; k++) {
        for (var m = 0; m < 4; m++) {
            if (m == 2) {
                break dance;
            }
        }
    }
}
ZPiDER
  • 4,264
  • 1
  • 17
  • 17
Noon Silk
  • 54,084
  • 6
  • 88
  • 105
54

You need to name your outer loop and break that loop, rather than your inner loop - like this.

outer_loop: 
for(i=0;i<5;i++) {
    for(j=i+1;j<5;j++) {
        break outer_loop;
    }
    alert(1);
}
Fenton
  • 241,084
  • 71
  • 387
  • 401
  • 4
    Wow, I didn't know we can name loops, great info! +1 – o.k.w Oct 14 '09 at 07:53
  • 12
    @o.k.w: you don't name the loop. You just label a position in the source. – xtofl Oct 14 '09 at 08:02
  • 7
    Never knew JavaScript supported labels. I wonder why I've never seen that before. :O – Nathan Taylor Oct 14 '09 at 08:19
  • 10
    @xtofl: Not exactly. You associate a label with a statement (which could be a loop) by placing it immediately before. It's only useful with a block statement, since the label is only available with the break and continue statements within the block. – Tim Down Oct 14 '09 at 08:48
  • @Nathan: probably because it's very poor practice: if you need to use labels in your code, it's a sign that you need to rewrite your code ;-) – NickFitz Oct 14 '09 at 09:53
  • 3
    @NickFitz: you could make a performance argument for it. In the case of nested loops labels could be useful to break out of an outer loop. While it may more elegant and modular to avoid nested loops by moving inner loops to separate functions, it will run marginally slower because of the extra function calls. – Tim Down Oct 14 '09 at 10:39
  • labels are the reason something like `onclick:"javascript: doThis()"` doesn't cause an error. `javascript:` is considered an unnecessary label in that case. – Ruan Mendes Dec 29 '12 at 01:07
40

There are at least five different ways to break out of two or more loops:

1) Set parent(s) loop to the end

for (i = 0; i < 5; i++)
{
    for (j = 0; j < 5; j++)
    {
        if (j === 2)
        {
            i = 5;
            break;
        }
    }
}

2) Use label

fast:
for (i = 0; i < 5; i++)
{
    for (j = 0; j < 5; j++)
    {
        if (j === 2)
            break fast;
    }
}

3) Use variable

var exit_loops = false;
for (i = 0; i < 5; i++)
{
    for (j = 0; j < 5; j++)
    {
        if (j === 2)
        {
            exit_loops = true;
            break;
        }
    }
    if (exit_loops)
        break;
}

4) Use self executing function

(function()
{
    for (i = 0; i < 5; i++)
    {
        for (j = 0; j < 5; j++)
        {
             if (j === 2)
                 return;
        }
    }
})();

5) Use regular function

function nested_loops()
{
    for (i = 0; i < 5; i++)
    {
        for (j = 0; j < 5; j++)
        {
             if (j === 2)
                 return;
        }
    }
}
nested_loops();
Dan Bray
  • 7,242
  • 3
  • 52
  • 70
30

See Aaron's. Otherwise: j=5;i=5 instead of break.

Glenn
  • 5,334
  • 4
  • 28
  • 31
  • This is simply the best and cleanest solution. Don't go back to using labels, they look awful. – Pedro Moreira Aug 07 '14 at 21:09
  • 1
    This is ugly. `for(i=0;i<5;i++)` is supposed to run 5 times. Updating `i` outside of the loop statement makes it behave in an unexpected way. – Florian F Nov 12 '14 at 08:34
  • 2
    Ugly is subjective. The loop is supposed to run as many times as you want it to run. The question was how to break a double for-loop, in that neither j or i run to 5. The only technical reason for favouring mine vs "break dance" is the case where you want i/j to show completion (==5) vs incompletion (== <5) post loops. – Glenn Nov 12 '14 at 21:52
  • Agree with @FlorianF, this is ugly in the sense that it seems to be a more error prone solution than adding a label, although I don't have any statistical evidence for that. Whether you are used to labels or not, they are certainly not an error-free concept, but hard coding numbers that you have to change at multiple places if one changes is a horrible programming style. As to the evaluation, it is a fair statement and helpful to determine the best answer for the OP. – Manuel Apr 24 '20 at 20:17
  • @Manuel: re:"horrible programming style". You're free to use consts etc for the numbers in both places, but that's not relevant to the question. Since this was answered in 2009, today I'd say you should rewrite your code so you don't need to use a for-loop. (filter, reduce, map, etc..) – Glenn Apr 28 '20 at 01:56
  • @Glenn the question is "how to break a for-loop", so the answer is still relevant today, regardless of the availability of higher order functions. If adding an additional var declaration is necessary to make this an answer that is actually practicable, then it should be added to the answer to reveal the full complexity. Practicability, maintainability, complexity are key factors when evaluating an answer. – Manuel Apr 28 '20 at 14:11
  • @Manuel there's a difference between production code and understanding how something works. The question is "how to break from nested loops", not "how do I write a maintainable loop for my production system". My answer works whether you use 5 or you write j = jSize ; i = iSize. Whether you want to use it or not is your choice. – Glenn Apr 28 '20 at 21:32
  • @Glenn You're right, the answer is a valid answer. It's just bad programming style as it currently is, that is why it is not suitable for production code, as you admit yourself. q.e.d. That is worth to be pointed out for novice programmers who do not see this as obviously. I dare to say that most people come to SO for advice. We want to give them good advice ;) – Manuel Apr 28 '20 at 21:50
  • Thanks for your approval... – Glenn Apr 28 '20 at 22:02
24
loop1:
    for (var i in set1) {
loop2:
        for (var j in set2) {
loop3:
            for (var k in set3) {
                break loop2;  // breaks out of loop3 and loop2
            }
        }
    }

code copied from Best way to break from nested loops in Javascript?

Please search before posting a question. The link was the FIRST related question I saw on the left side of this page!

Community
  • 1
  • 1
Jim
  • 5,557
  • 1
  • 20
  • 18
11

Unfortunately you'll have to set a flag or use labels (think old school goto statements)

var breakout = false;

for(i=0;i<5;i++)
{
    for(j=i+1;j<5;j++)
    {
        breakout = true;
        break;
    }
    if (breakout) break;
    alert(1)
};

The label approach looks like:

end_loops:
for(i=0;i<5;i++)
{
    for(j=i+1;j<5;j++)
    {
        break end_loops;
    }
    alert(1)
};

edit: label incorrectly placed.

also see:

Nicolás Ozimica
  • 9,481
  • 5
  • 38
  • 51
Jonathan Fingland
  • 56,385
  • 11
  • 85
  • 79
  • 1
    So the label can't go downstream of the break correct? Like lets say okay some condition was met I don't need the loops at all. Can a branch to a label declared after the loops be made? – eaglei22 Jul 12 '17 at 16:34
6

In my opinion, it's important to keep your construct vocabulary to a minimum. If I can do away with breaks and continues easily, I do so.

function foo ()
{
    var found = false;
    for(var k = 0; (k < 4 && !found); k++){
        for(var m = 0; (m < 4 && !found); m++){
           if( m === 2){
               found = true;
           }
        }
    }
    return found;
}

Be warned, after the loop, m and k are one larger that you might think. This is because m++ and k++ are executed before their loop conditions. However, it's still better than 'dirty' breaks.

EDIT: long comment @Dennis...

I wasn't being 100% serious about being 'dirty', but I still think that 'break' contravenes my own conception of clean code. The thought of having multi-level breaks actually makes me feel like taking a shower.

I find justifying what I mean about a feeling about code because I have coded all life. The best why I can think of it is is a combination of manners and grammar. Breaks just aren't polite. Multi level breaks are just plain rude.

When looking at a for statement, a reader knows exactly where to look. Everything you need to know about the rules of engagement are in the contract, in between the parenthesis. As a reader, breaks insult me, it feels like I've been cheated upon.

Clarity is much more respectful than cheating.

thomas-peter
  • 7,738
  • 6
  • 43
  • 58
  • Why should you need to keep your construct vocab to a minimum? The argument that breaks are 'dirty' is absurd. In terms of readability, your solution is much worse, and it performs no better. You have a point though, like any construct, breaks can be abused, but a bit of cheating here or there for readability purposes is definitely okay. – Dennis Jul 10 '12 at 21:41
  • too long to fit into a comment to i did an edit. – thomas-peter Jul 13 '12 at 12:06
  • Also, keeping construct vocabulary to a minimum is more of a result of switching between many languages frequently. You tend to use more language that is common between them. In the case of JavaScript, this has the benefit of making the code compatible across systems and also benefits readers who may not use JavaScript as their primary language. – thomas-peter Jul 13 '12 at 12:37
  • 1
    +1 for a different approach. It's good to have options – Phil Strong Aug 30 '12 at 12:17
  • adding the test in two loops is more likely to cause errors than a `break` or `continue`. In this case, you can simply return when you find a match – Ruan Mendes Dec 29 '12 at 01:05
5

Use function for multilevel loops - this is good way:

function find_dup () {
    for (;;) {
        for(;;) {
            if (done) return;
        }
    }
}
Anatoliy
  • 29,485
  • 5
  • 46
  • 45
4

Wrap in a self executing function and return

(function(){
    for(i=0;i<5;i++){
        for (j=0;j<3;j++){
            //console.log(i+' '+j);
            if (j == 2) return;
        }
    }
})()
kehers
  • 4,076
  • 3
  • 30
  • 31
2

You return to "break" you nested for loop.

function foo ()
{
    //dance:
    for(var k = 0; k < 4; k++){
        for(var m = 0; m < 4; m++){
            if(m == 2){
                //break dance;
                return;
            }
        }
    }
}
foo();
GibboK
  • 71,848
  • 143
  • 435
  • 658
-1

break doesn't take parameters. There are two workarounds:

  1. Wrap them in a function and call return

  2. Set a flag in the inner loop and break again right after the loop if the flag is set.

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
-1

Break 1st loop:

for(i=0;i<5;i++)
{
  for(j=i+1;j<5;j++)
  {
    //do something

    break;
  }
  alert(1);
};

Break both loops:

for(i=0;i<5;i++)
{
  var breakagain = false;
  for(j=i+1;j<5;j++)
  {
    //do something

    breakagain = true;
    break;
  }
  alert(1);
  if(breakagain)
    break;
};
o.k.w
  • 25,490
  • 6
  • 66
  • 63
-1

You can break nested for loops with the word 'break', it works without any labels.

In your case you need to have a condition which is sufficient to break a loop.

Here's an example:

var arr = [[1,3], [5,6], [9,10]];
for (var a = 0; a<arr.length; a++ ){
  for (var i=0; i<arr[a].length; i++) {
    console.log('I am a nested loop and i = ' + i);
    if (i==0) { break; }
  }
  console.log('first loop continues');
}

It logs the following:

> I am a nested loop and i = 0 
> first loop continues
> I am a nested loop and i = 0 
> first loop continues
> I am a nested loop and i = 0 
> first loop continues

The return; statement does not work in this case. Working pen

Ilya Kushlianski
  • 780
  • 9
  • 15
-9
function myFunction(){
  for(var i = 0;i < n;i++){
    for(var m = 0;m < n;m++){
      if(/*break condition*/){
        goto out;
      }
    }
  }
out:
 //your out of the loop;
}
junmats
  • 1,894
  • 2
  • 23
  • 36
  • 3
    In Javascript, "goto" may be a reserved word, but it doesn't actually do anything... – NickFitz Oct 14 '09 at 09:51
  • Downvoted, same reason as NickFitz. – Tim Down Oct 14 '09 at 11:27
  • @NickFitz, nope, `goto` is not a reserved word in JavaScript: `ReferenceError: goto is not defined` – Derek 朕會功夫 Feb 25 '12 at 03:42
  • 1
    @Derek朕會功夫 It's a "[future reserved word](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Reserved_Words#In_ECMAScript_2)" (in some ECMAScript standards), i.e. it's not implemented yet but might be in the future. – JJJ Jan 24 '14 at 17:58