254

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?

7
  • 3
    break ( 2) ; :o what do you mean by 2, break can't have any arguments Commented Oct 14, 2009 at 7:51
  • 3
    Line 7 is missing a semicolon after alert(1). Commented Oct 14, 2009 at 8:18
  • 24
    @Nathan Taylor: semicolons are optional in JavaScript, but considered good style Commented Oct 14, 2009 at 8:41
  • 1
    Near duplicate of stackoverflow.com/q/183161/149391 Commented Jun 13, 2012 at 9:57
  • 1
    @RakeshJuyal it does in other languages such as C Commented Feb 4, 2015 at 10:11

14 Answers 14

672

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;
            }
        }
    }
}
Sign up to request clarification or add additional context in comments.

6 Comments

break dance har har
There's also the fact that JS requires this giant involved dance. Other languages give you a break (literally, like break 2).
Would it be the same if dance: was after the for? Or does the label need to be read before the break?
By the way, why does breaking the parent loop also break the child loop instantly?
If the parent loop isn't being executed, how could the child loop be?
|
55

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);
}

7 Comments

Wow, I didn't know we can name loops, great info! +1
@o.k.w: you don't name the loop. You just label a position in the source.
Never knew JavaScript supported labels. I wonder why I've never seen that before. :O
@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.
@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.
|
43

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();

3 Comments

The whole point of a multi-level break is to avoid #3.
break fast 😄
Never knew of using labels, I'm gonna use that heaps now
30

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

9 Comments

This is simply the best and cleanest solution. Don't go back to using labels, they look awful.
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.
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.
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: 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..)
|
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!

Comments

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:

1 Comment

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?
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.

5 Comments

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.
too long to fit into a comment to i did an edit.
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.
+1 for a different approach. It's good to have options
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
5

Use function for multilevel loops - this is good way:

function find_dup () {
    for (;;) {
        for(;;) {
            if (done) return;
        }
    }
}

2 Comments

Wooo, what the heck is for(;;)? Never seen that before.
Infinity loop :) it's like while (true) {}
3

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;
        }
    }
})()

Comments

1

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();

1 Comment

This exits the entire function rather than just breaking the loop.
-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.

2 Comments

Aaron: I just tested in IE6; it does :)
-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;
};

Comments

-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

Comments

-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;
}

4 Comments

In Javascript, "goto" may be a reserved word, but it doesn't actually do anything...
Downvoted, same reason as NickFitz.
@NickFitz, nope, goto is not a reserved word in JavaScript: ReferenceError: goto is not defined
@Derek朕會功夫 It's a "future reserved word" (in some ECMAScript standards), i.e. it's not implemented yet but might be in the future.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.