|
|
--- |
|
|
title: Labeled statement |
|
|
slug: Web/JavaScript/Reference/Statements/label |
|
|
page-type: javascript-statement |
|
|
browser-compat: javascript.statements.label |
|
|
sidebar: jssidebar |
|
|
--- |
|
|
|
|
|
A **labeled statement** is any [statement](/en-US/docs/Web/JavaScript/Reference/Statements) that is prefixed with an identifier. You can jump to this label using a {{jsxref("Statements/break", "break")}} or {{jsxref("Statements/continue", "continue")}} statement nested within the labeled statement. |
|
|
|
|
|
{{InteractiveExample("JavaScript Demo: Labeled statement", "taller")}} |
|
|
|
|
|
```js interactive-example |
|
|
let i, j; |
|
|
|
|
|
loop1: for (i = 0; i < 3; i++) { |
|
|
loop2: for (j = 0; j < 3; j++) { |
|
|
if (i === 1 && j === 1) { |
|
|
break loop1; |
|
|
} |
|
|
console.log(`i = ${i}, j = ${j}`); |
|
|
} |
|
|
} |
|
|
|
|
|
// Expected output: |
|
|
// "i = 0, j = 0" |
|
|
// "i = 0, j = 1" |
|
|
// "i = 0, j = 2" |
|
|
// "i = 1, j = 0" |
|
|
``` |
|
|
|
|
|
## Syntax |
|
|
|
|
|
```js-nolint |
|
|
label: |
|
|
statement |
|
|
``` |
|
|
|
|
|
- `label` |
|
|
- : Any JavaScript [identifier](/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#identifiers) that is not a [reserved word](/en-US/docs/Web/JavaScript/Reference/Lexical_grammar#reserved_words). |
|
|
- `statement` |
|
|
- : A JavaScript statement. `break` can be used within any labeled statement, and `continue` can be used within labeled looping statements. |
|
|
|
|
|
## Description |
|
|
|
|
|
You can use a label to identify a statement, and later refer to it using a `break` or `continue` statement. Note that JavaScript has _no_ `goto` statement; you can only use labels with `break` or `continue`. |
|
|
|
|
|
Any `break` or `continue` that references `label` must be contained within the `statement` that's labeled by `label`. Think about `label` as a variable that's only available in the scope of `statement`. |
|
|
|
|
|
If a `break label;` statement is encountered when executing `statement`, execution of `statement` terminates, and execution continues at the statement immediately following the labeled statement. |
|
|
|
|
|
`continue label;` can only be used if `statement` is one of the [looping statements](/en-US/docs/Web/JavaScript/Reference/Statements#iterations). If a `continue label;` statement is encountered when executing `statement`, execution of `statement` continues at the next iteration of the loop. `continue;` without a label can only continue the innermost loop, while `continue label;` allows continuing any given loop even when the statement is nested within other loops. |
|
|
|
|
|
A statement can have multiple labels. In this case, the labels are all functionally equivalent. |
|
|
|
|
|
## Examples |
|
|
|
|
|
### Using a labeled continue with for loops |
|
|
|
|
|
```js |
|
|
// The first for statement is labeled "loop1" |
|
|
loop1: for (let i = 0; i < 3; i++) { |
|
|
// The second for statement is labeled "loop2" |
|
|
loop2: for (let j = 0; j < 3; j++) { |
|
|
if (i === 1 && j === 1) { |
|
|
continue loop1; |
|
|
} |
|
|
console.log(`i = ${i}, j = ${j}`); |
|
|
} |
|
|
} |
|
|
|
|
|
// Logs: |
|
|
// i = 0, j = 0 |
|
|
// i = 0, j = 1 |
|
|
// i = 0, j = 2 |
|
|
// i = 1, j = 0 |
|
|
// i = 2, j = 0 |
|
|
// i = 2, j = 1 |
|
|
// i = 2, j = 2 |
|
|
``` |
|
|
|
|
|
Notice how it skips both "i = 1, j = 1" and "i = 1, j = 2". |
|
|
|
|
|
### Using a labeled break with for loops |
|
|
|
|
|
```js |
|
|
let i, j; |
|
|
|
|
|
// The first for statement is labeled "loop1" |
|
|
loop1: for (i = 0; i < 3; i++) { |
|
|
// The second for statement is labeled "loop2" |
|
|
loop2: for (j = 0; j < 3; j++) { |
|
|
if (i === 1 && j === 1) { |
|
|
break loop1; |
|
|
} |
|
|
console.log(`i = ${i}, j = ${j}`); |
|
|
} |
|
|
} |
|
|
|
|
|
// Logs: |
|
|
// i = 0, j = 0 |
|
|
// i = 0, j = 1 |
|
|
// i = 0, j = 2 |
|
|
// i = 1, j = 0 |
|
|
``` |
|
|
|
|
|
Notice the difference with the previous `continue` example: when `break loop1` is encountered, the execution of the outer loop is terminated, so there are no further logs beyond "i = 1, j = 0"; when `continue loop1` is encountered, the execution of the outer loop continues at the next iteration, so only "i = 1, j = 1" and "i = 1, j = 2" are skipped. |
|
|
|
|
|
### Using a labeled continue statement |
|
|
|
|
|
Given an array of items and an array of tests, this example counts the number of items that pass all the tests. |
|
|
|
|
|
```js |
|
|
// Numbers from 1 to 100 |
|
|
const items = Array.from({ length: 100 }, (_, i) => i + 1); |
|
|
const tests = [ |
|
|
{ pass: (item) => item % 2 === 0 }, |
|
|
{ pass: (item) => item % 3 === 0 }, |
|
|
{ pass: (item) => item % 5 === 0 }, |
|
|
]; |
|
|
let itemsPassed = 0; |
|
|
|
|
|
itemIteration: for (const item of items) { |
|
|
for (const test of tests) { |
|
|
if (!test.pass(item)) { |
|
|
continue itemIteration; |
|
|
} |
|
|
} |
|
|
|
|
|
itemsPassed++; |
|
|
} |
|
|
``` |
|
|
|
|
|
Note how the `continue itemIteration;` statement skips the rest of the tests for the current item as well as the statement that updates the `itemsPassed` counter, and continues with the next item. If you don't use a label, you would need to use a boolean flag instead. |
|
|
|
|
|
```js |
|
|
// Numbers from 1 to 100 |
|
|
const items = Array.from({ length: 100 }, (_, i) => i + 1); |
|
|
const tests = [ |
|
|
{ pass: (item) => item % 2 === 0 }, |
|
|
{ pass: (item) => item % 3 === 0 }, |
|
|
{ pass: (item) => item % 5 === 0 }, |
|
|
]; |
|
|
let itemsPassed = 0; |
|
|
|
|
|
for (const item of items) { |
|
|
let passed = true; |
|
|
for (const test of tests) { |
|
|
if (!test.pass(item)) { |
|
|
passed = false; |
|
|
break; |
|
|
} |
|
|
} |
|
|
if (passed) { |
|
|
itemsPassed++; |
|
|
} |
|
|
} |
|
|
``` |
|
|
|
|
|
### Using a labeled break statement |
|
|
|
|
|
Given an array of items and an array of tests, this example determines whether all items pass all tests. |
|
|
|
|
|
```js |
|
|
// Numbers from 1 to 100 |
|
|
const items = Array.from({ length: 100 }, (_, i) => i + 1); |
|
|
const tests = [ |
|
|
{ pass: (item) => item % 2 === 0 }, |
|
|
{ pass: (item) => item % 3 === 0 }, |
|
|
{ pass: (item) => item % 5 === 0 }, |
|
|
]; |
|
|
let allPass = true; |
|
|
|
|
|
itemIteration: for (const item of items) { |
|
|
for (const test of tests) { |
|
|
if (!test.pass(item)) { |
|
|
allPass = false; |
|
|
break itemIteration; |
|
|
} |
|
|
} |
|
|
} |
|
|
``` |
|
|
|
|
|
Again, if you don't use a label, you would need to use a boolean flag instead. |
|
|
|
|
|
```js |
|
|
// Numbers from 1 to 100 |
|
|
const items = Array.from({ length: 100 }, (_, i) => i + 1); |
|
|
const tests = [ |
|
|
{ pass: (item) => item % 2 === 0 }, |
|
|
{ pass: (item) => item % 3 === 0 }, |
|
|
{ pass: (item) => item % 5 === 0 }, |
|
|
]; |
|
|
let allPass = true; |
|
|
|
|
|
for (const item of items) { |
|
|
let passed = true; |
|
|
for (const test of tests) { |
|
|
if (!test.pass(item)) { |
|
|
passed = false; |
|
|
break; |
|
|
} |
|
|
} |
|
|
if (!passed) { |
|
|
allPass = false; |
|
|
break; |
|
|
} |
|
|
} |
|
|
``` |
|
|
|
|
|
### Using a labeled block with break |
|
|
|
|
|
You can label statements other than loops, such as simple blocks, but only `break` statements can reference non-loop labels. |
|
|
|
|
|
```js |
|
|
foo: { |
|
|
console.log("face"); |
|
|
break foo; |
|
|
console.log("this will not be executed"); |
|
|
} |
|
|
console.log("swap"); |
|
|
|
|
|
// Logs: |
|
|
// "face" |
|
|
// "swap" |
|
|
``` |
|
|
|
|
|
### Labeled function declarations |
|
|
|
|
|
Labels can only be applied to [statements, not declarations](/en-US/docs/Web/JavaScript/Reference/Statements#difference_between_statements_and_declarations). There is a legacy grammar that allows function declarations to be labeled in non-strict code: |
|
|
|
|
|
```js |
|
|
L: function F() {} |
|
|
``` |
|
|
|
|
|
In [strict mode](/en-US/docs/Web/JavaScript/Reference/Strict_mode) code, however, this will throw a {{jsxref("SyntaxError")}}: |
|
|
|
|
|
```js-nolint example-bad |
|
|
"use strict"; |
|
|
L: function F() {} |
|
|
// SyntaxError: functions cannot be labelled |
|
|
``` |
|
|
|
|
|
Non-plain functions, such as [generator functions](/en-US/docs/Web/JavaScript/Reference/Statements/function*) and [async functions](/en-US/docs/Web/JavaScript/Reference/Statements/async_function) can neither be labeled in strict code, nor in non-strict code: |
|
|
|
|
|
```js-nolint example-bad |
|
|
L: function* F() {} |
|
|
// SyntaxError: generator functions cannot be labelled |
|
|
``` |
|
|
|
|
|
The labeled function declaration syntax is [deprecated](/en-US/docs/Web/JavaScript/Reference/Deprecated_and_obsolete_features) and you should not use it, even in non-strict code. You cannot actually jump to this label within the function body. |
|
|
|
|
|
## Specifications |
|
|
|
|
|
{{Specifications}} |
|
|
|
|
|
## Browser compatibility |
|
|
|
|
|
{{Compat}} |
|
|
|
|
|
## See also |
|
|
|
|
|
- {{jsxref("Statements/break", "break")}} |
|
|
- {{jsxref("Statements/continue", "continue")}} |
|
|
|