break verlässt eine Schleife oder ein switch-Statement vorzeitig. continue überspringt den Rest des aktuellen Durchlaufs und springt zur nächsten Iteration. Beide Statements wirken standardmäßig nur auf die innerste Schleife. Für äußere Schleifen gibt es Labels — eine wenig genutzte Syntax, die in seltenen Fällen aber genau das Richtige ist. Dieser Artikel zeigt die Grundformen, dokumentiert das Label-Feature und nennt die wenigen Stellen, an denen Labels einer Alternative überlegen sind.
break in Schleifen
break verlässt die Schleife sofort. Die Ausführung springt zur ersten Anweisung nach der Schleife.
function findeErsteGerade(arr) {
for (const x of arr) {
if (x % 2 === 0) {
return x; // alternativ: break + Variable
}
}
return undefined;
}
console.log(findeErsteGerade([1, 3, 7, 4, 9])); // 4
// Klassisch mit break
const arr = [1, 3, 7, 4, 9];
let gefunden;
for (const x of arr) {
if (x % 2 === 0) {
gefunden = x;
break; // sofortiger Ausstieg
}
}
console.log(gefunden); // 44
4In Funktionen ist meist return lesbarer als break mit Variable — keine Zwischen-Schritte, keine Variable außerhalb der Schleife. break ist relevant, wenn man die Schleife verlässt, aber nicht die ganze Funktion.
break in switch
break ist in switch der Standard-Terminator, um Fall-through zu verhindern. Detail-Behandlung im switch-Artikel.
function farbe(level) {
let result;
switch (level) {
case 'info': result = 'blue'; break;
case 'warn': result = 'orange'; break;
case 'error': result = 'red'; break;
default: result = 'gray';
}
return result;
}
console.log(farbe('warn')); // 'orange'orangecontinue — zur nächsten Iteration
continue überspringt den Rest des aktuellen Schleifen-Durchlaufs. In for springt es zum Update-Teil (i++ etc.), in while direkt zur Bedingung.
// Nur gerade Zahlen verarbeiten
for (let i = 0; i < 10; i++) {
if (i % 2 !== 0) continue;
console.log('gerade:', i);
}gerade: 0
gerade: 2
gerade: 4
gerade: 6
gerade: 8continue ist eine Stil-Frage: manche Style-Guides bevorzugen die invertierte Form if (gerade) { ... } ohne continue, andere finden continue als Guard-Clause der Schleife klarer. Für lange Schleifen-Bodies mit mehreren Filter-Bedingungen sind frühe continue-Statements analog zu Early-Returns oft die Sieger.
Standardmäßig nur die innerste Schleife
Sowohl break als auch continue wirken nur auf die innerste umschließende Schleife.
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (j === 1) break; // bricht NUR die innere Schleife ab
console.log(`i=${i}, j=${j}`);
}
}i=0, j=0
i=1, j=0
i=2, j=0Die äußere i-Schleife läuft normal weiter. Für „beide Schleifen verlassen" braucht es entweder ein Label, ein Flag, eine ausgelagerte Funktion mit return oder eine throw-Konstruktion (zu drastisch).
Labels — name: schleife
Eine Label-Definition ist ein Identifier gefolgt von Doppelpunkt, direkt vor einer Schleife oder einem Block. Mit break name; oder continue name; adressiert man dann genau dieses Label.
aussen: for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (j === 1) break aussen; // bricht BEIDE Schleifen
console.log(`i=${i}, j=${j}`);
}
}i=0, j=0Das gleiche funktioniert mit continue: continue label springt in den Update-/Bedingungs-Teil der labelten Schleife.
aussen: for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (j === 1) continue aussen; // nächstes i
console.log(`i=${i}, j=${j}`);
}
}i=0, j=0
i=1, j=0
i=2, j=0Diese Form ist die einzige, in der continue label außerhalb der labelten Schleife semantisch Sinn ergibt: vom Inneren der inneren Schleife direkt in den nächsten Durchlauf der äußeren springen.
Labels auf Blöcken
Labels können auch Blöcke kennzeichnen — nicht nur Schleifen. Mit break label; lässt sich der Block dann „nach unten" verlassen.
verarbeitung: {
console.log('Start');
if (true) break verarbeitung; // verlässt den Block
console.log('Nie erreicht');
}
console.log('Nach Block');Start
Nach BlockDas ist eine sehr seltene Form. Manche Codebasen nutzen sie als „strukturiertes goto" für komplexe Validierungs-Logik. In den meisten Fällen ist eine Funktion mit Early-Returns lesbarer.
Alternativen zu Labels
In modernen Codebasen sind Labels selten. Die häufigeren Wege, denselben Effekt zu erreichen:
// Variante 1: Funktion mit return
function suche(matrix, ziel) {
for (let i = 0; i < matrix.length; i++) {
for (let j = 0; j < matrix[i].length; j++) {
if (matrix[i][j] === ziel) return [i, j];
}
}
return null;
}
console.log(suche([[1, 2], [3, 4]], 4)); // [1, 1]
// Variante 2: Flag
function sucheFlag(matrix, ziel) {
let pos = null;
outerSearch:
for (let i = 0; i < matrix.length; i++) {
for (let j = 0; j < matrix[i].length; j++) {
if (matrix[i][j] === ziel) {
pos = [i, j];
break outerSearch;
}
}
}
return pos;
}
console.log(sucheFlag([[1, 2], [3, 4]], 4));
// Variante 3: some / find — fertige Methoden
function sucheFunctional(matrix, ziel) {
const i = matrix.findIndex(row => row.includes(ziel));
if (i < 0) return null;
return [i, matrix[i].indexOf(ziel)];
}
console.log(sucheFunctional([[1, 2], [3, 4]], 4));[ 1, 1 ]
[ 1, 1 ]
[ 1, 1 ]Faustregel: Funktion mit return ist meist die sauberste Form. Labels sind das letzte Mittel, wenn die Funktion aus anderen Gründen nicht zerlegt werden soll.
Label-Konventionen
Labels sind keine Variablen — sie leben in einem eigenen Namensraum. Aber Style-Guides empfehlen klare Konvention:
- Labels GROSSGESCHRIEBEN oder mit Suffix (
_loop,_block) — visuell von Variablen unterscheidbar. - Nur direkt vor der Schleife/dem Block — kein Code dazwischen.
- Niemals mit Variablen-Namen kollidieren — auch wenn die Sprache es erlauben würde.
// Empfohlene Konvention
OUTER: for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (i * j > 4) break OUTER;
console.log(i, j);
}
}0 0
0 1
0 2
1 0
1 1
1 2
2 0
2 1
2 2ESLint hat dazu die Regeln no-labels (Labels komplett verbieten) und no-extra-label (unnötige Labels). Viele Codebasen aktivieren no-labels als Default und erlauben sie nur per // eslint-disable-next-line.
break/continue funktioniert NICHT in forEach
arr.forEach(callback) ruft den Callback in einer eigenen Funktion auf. Innerhalb einer Funktion sind break und continue ungültig — SyntaxError.
[1, 2, 3].forEach(x => {
if (x === 2) break; // SyntaxError: Illegal break statement
console.log(x);
});Lösungsalternativen, wenn man Abbruch braucht:
for...ofmitbreak— die idiomatische Wahl.Array.prototype.some()— bricht ab, sobald der Callback truthy zurückgibt.Array.prototype.every()— bricht ab, sobald der Callback falsy zurückgibt.Array.prototype.find()/findIndex()— wenn man genau ein Element sucht.
// some als Abbruch-Mechanik
[1, 2, 3, 4].some(x => {
console.log('verarbeite', x);
return x === 2; // true → some bricht ab
});verarbeite 1
verarbeite 2some als Abbruch-Werkzeug ist syntaktisch ein bisschen schräg (der Boolean-Rückgabewert ist „eigentlich" der Treffer-Indikator, nicht ein „brich-jetzt-ab"-Signal). Lesbarer ist meist die for...of-Version.
Besonderheiten
Labels sind in JavaScript verfügbar, aber selten genutzt
Anders als goto in C ist die Label-Syntax in JavaScript auf break/continue beschränkt — kein freier Sprung. Daher sind sie strukturell sicher. Trotzdem sind sie in modernen Codebasen rar: meist gibt es eine lesbarere Alternative (Funktion mit return, Flag, Array-Methode).
continue mit Label springt in äußere Schleife, nicht raus
Wichtige Unterscheidung: break label verlässt die Schleife, continue label macht in der Schleife mit dem nächsten Durchlauf weiter. continue aussen in einer verschachtelten Schleife heißt also: innere Schleife komplett überspringen, nächstes i++ der äußeren Schleife.
break ohne Argument funktioniert nicht in Funktionen
break ohne Label sucht die nächste umschließende Schleife oder switch. Wenn die nächste umschließende Konstruktion eine Funktion ist (z.B. ein forEach-Callback), wirft das einen SyntaxError. Innerhalb von Callback-basierten Methoden gibt es kein break — nur return aus dem Callback, das aber lediglich diesen einen Durchlauf beendet.
Label-Namensraum ist eigen — keine Variablen-Kollision
Ein Label outer kollidiert nicht mit einer Variable namens outer. Das ist eine Spec-Eigenschaft (eigener „Label Set" pro Funktion). Trotzdem unschöner Stil — Labels in Großbuchstaben oder mit Suffix kennzeichnen, um Verwechslung mit Variablen visuell zu vermeiden.
Block-Label + break: strukturiertes 'früh raus'
verarbeitung: { ... break verarbeitung; ... } erlaubt es, einen Block-Body vorzeitig zu verlassen. Das ist eines der wenigen Konstrukte, die sich wie ein eingeschränktes goto anfühlen. Praktisch fast nie nötig — eine Funktion mit Early-Returns macht dasselbe lesbarer.
break in finally — unterdrückt Exception
Wenn ein break oder return innerhalb eines finally-Blocks ausgeführt wird, „verschluckt" das eine eventuell ausstehende Exception aus dem try-Block. Linter wie ESLint warnen mit no-unsafe-finally. In sauberem Code: kein Control-Flow-Statement in finally.
ESLint no-labels: viele Codebasen verbieten Labels komplett
Airbnb, StandardJS und mehrere große Open-Source-Projekte haben no-labels aktiviert. Begründung: in 99 % der Fälle gibt es eine lesbarere Alternative. Wenn du Labels nutzen willst, ist das Opt-in über // eslint-disable-next-line no-labels die akzeptierte Form.
break aus mehreren switch-Ebenen ist ungewöhnlich, aber möglich
Ein switch innerhalb eines switch (selten gesehen): das innere break verlässt nur den inneren switch. Wer das äußere meinen will, braucht ein Label am äußeren switch. Lesbarer ist meistens: inneren switch in eine Funktion auslagern.