Labelled statements, break, and continue
These are actually features of any C-style language. Any statement can be labelled, and continue and break statements can target them:
outer: for (var i = 0; i < 5; i++)
for (var j = 0; j < 10; j++) {
document.write('[' + i + ','+ j + ']');
if (j == 1)
break outer;
}
As that example shows, the |break outer;| ends execution of the whole loop. This example outputs: [0,0][0,1]
outer: for (var i = 0; i < 5; i++)
for (var j = 0; j < 10; j++) {
document.write('[' + i + ','+ j + ']');
if (j == 1)
continue outer;
}
In this example, the |continue outer;| skips the rest of the current iteration and goes to the next iteration of the loop. This example outputs: [0,0][0,1][1,0][1,1][2,0][2,1][3,0][3,1][4,0][4,1]
Break and continue statements can only target labels they are nested in. That means they can’t be used as a generic goto statement. For example,
label: some_statement;
//...
break label;
wouldn’t work.
Labelled statements and break, revisited
The above are pretty well-known features. Now comes the interesting part.
label: if (cond) {
for (var i = 0; i < 10; i++)
if (obj[i] == [/i]null)
break label;
alert('obj has no null elements');
}
That would work exactly how’d you expect it to work. That’s right - any statement can be a label, and breaks can target them in the same way. The only differences are:
[list=1][]The continue statement can’t be used here - continue statements can only be used on loops.
[]The breaks must have label targets - it must be |break label;| instead of just |break;|. |break;| would only work in loops.[/list]
That’s not all. There’s another statement that can be used to abstract this break to label functionality to anything: the block statement, i.e. |{ … }|.
label: {
for (var i = 0; i < 10; i++)
if (obj[i] == [/i]null)
break label;
alert('obj has no null elements');
}
That’s the same as the above, except without the |if|. This means there’s no need for weird hacks like this:
label: do {
if (cond1)
break label;
statement1;
statement2;
statement3;
statement4;
if (cond2)
break label;
statement5;
statement6;
} while (0);
or equivalently:
if (cond2) {
statement1;
statement2;
statement3;
statement4;
} else if (!cond1) {
statement1;
statement2;
statement3;
statement4;
statement5;
statement6;
}
They can be replaced with:
label: {
if (cond1)
break label;
statement1;
statement2;
statement3;
statement4;
if (cond2)
break label;
statement5;
statement6;
}
A note on block statements
Unlike C/C++, the block statement in JS does not introduce a new scope. For example, in C++:
int a = 1;
{
int a = 2;
cout << a;
}
cout << a;
would output: 12.
The equivalent in JS (in the HTML environment):
var a = 1;
{
var a = 2;
document.write(a);
}
document.write(a);
would output: 22. That means, that the inner a and the outer a are actually the same thing. To illustrate the point further:
{
int a = 1;
cout << a;
}
cout << a;
would be a syntax error in C++, while the equivalent in JS:
{
var a = 1;
document.write(a);
}
document.write(a);
would output: 11.