break und continuebreakbreak mit Label: Verlassen jeder beschrifteten Anweisungcontinueif-Anweisungen [ES1]if-Anweisungenswitch-Anweisungen [ES3]switch-Anweisungreturn oder break!case-Klauselndefault-Klauselwhile-Schleifen [ES1]while-Schleifendo-while-Schleifen [ES3]for-Schleifen [ES1]for-Schleifenfor-of-Schleifen [ES6]const: for-of vs. forfor-await-of-Schleifen [ES2018]for-in-Schleifen (vermeiden) [ES1]Dieses Kapitel behandelt die folgenden Kontrollflussanweisungen
if-Anweisung [ES1]switch-Anweisung [ES3]while-Schleife [ES1]do-while-Schleife [ES3]for-Schleife [ES1]for-of-Schleife [ES6]for-await-of-Schleife [ES2018]for-in-Schleife [ES1]break und continueDie beiden Operatoren break und continue können verwendet werden, um Schleifen und andere Anweisungen zu kontrollieren, während wir uns darin befinden.
breakEs gibt zwei Versionen von break: eine mit einem Operanden und eine ohne. Die letztere Version funktioniert innerhalb der folgenden Anweisungen: while, do-while, for, for-of, for-await-of, for-in und switch. Sie verlässt sofort die aktuelle Anweisung
for (const x of ['a', 'b', 'c']) {
console.log(x);
if (x === 'b') break;
console.log('---')
}
// Output:
// 'a'
// '---'
// 'b'break mit Label: Verlassen jeder beschrifteten Anweisungbreak mit einem Operanden funktioniert überall. Sein Operand ist ein Label. Labels können vor jede Anweisung gesetzt werden, einschließlich Blöcken. break my_label verlässt die Anweisung, deren Label my_label ist
my_label: { // label
if (condition) break my_label; // labeled break
// ···
}Im folgenden Beispiel kann die Suche entweder
result zu finden. Dies wird direkt nach der Schleife behandelt (Zeile B).result. Dann verwenden wir break mit Label (Zeile A), um den Code zu überspringen, der den Fehlschlag behandelt.function findSuffix(stringArray, suffix) {
let result;
search_block: {
for (const str of stringArray) {
if (str.endsWith(suffix)) {
// Success:
result = str;
break search_block; // (A)
}
} // for
// Failure:
result = '(Untitled)'; // (B)
} // search_block
return { suffix, result };
// Same as: {suffix: suffix, result: result}
}
assert.deepEqual(
findSuffix(['notes.txt', 'index.html'], '.html'),
{ suffix: '.html', result: 'index.html' }
);
assert.deepEqual(
findSuffix(['notes.txt', 'index.html'], '.mjs'),
{ suffix: '.mjs', result: '(Untitled)' }
);continuecontinue funktioniert nur innerhalb von while, do-while, for, for-of, for-await-of und for-in. Es verlässt sofort die aktuelle Schleifeniteration und fährt mit der nächsten fort – zum Beispiel
const lines = [
'Normal line',
'# Comment',
'Another normal line',
];
for (const line of lines) {
if (line.startsWith('#')) continue;
console.log(line);
}
// Output:
// 'Normal line'
// 'Another normal line'if, while und do-while haben Bedingungen, die prinzipiell boolesch sind. Eine Bedingung muss jedoch nur truthy (true sein, wenn zu einem booleschen Wert konvertiert) sein, um akzeptiert zu werden. Mit anderen Worten, die folgenden beiden Kontrollflussanweisungen sind äquivalent
if (value) {}
if (Boolean(value) === true) {}Dies ist eine Liste aller falsy Werte
undefined, nullfalse0, NaN0n''Alle anderen Werte sind truthy. Weitere Informationen finden Sie unter §15.2 „Falsy und truthy Werte“.
if-Anweisungen [ES1]Dies sind zwei einfache if-Anweisungen: eine mit nur einem „then“-Zweig und eine mit sowohl einem „then“-Zweig als auch einem „else“-Zweig
if (cond) {
// then branch
}
if (cond) {
// then branch
} else {
// else branch
}Anstelle des Blocks kann auf else auch eine weitere if-Anweisung folgen
if (cond1) {
// ···
} else if (cond2) {
// ···
}
if (cond1) {
// ···
} else if (cond2) {
// ···
} else {
// ···
}Sie können diese Kette mit weiteren else ifs fortsetzen.
if-AnweisungenDer allgemeine Aufbau von if-Anweisungen ist
if (cond) «then_statement»
else «else_statement»Bisher war die then_statement immer ein Block, aber wir können jede beliebige Anweisung verwenden. Diese Anweisung muss mit einem Semikolon abgeschlossen werden
if (true) console.log('Yes'); else console.log('No');Das bedeutet, dass else if kein eigener Konstrukt ist; es ist einfach eine if-Anweisung, deren else_statement eine weitere if-Anweisung ist.
switch-Anweisungen [ES3]Eine switch-Anweisung sieht wie folgt aus
switch («switch_expression») {
«switch_body»
}
Der Körper von switch besteht aus null oder mehr case-Klauseln
case «case_expression»:
«statements»
Und optional eine default-Klausel
default:
«statements»
Eine switch wird wie folgt ausgeführt
switch-AnweisungBetrachten wir ein Beispiel: Die folgende Funktion konvertiert eine Zahl von 1–7 in den Namen eines Wochentags.
function dayOfTheWeek(num) {
switch (num) {
case 1:
return 'Monday';
case 2:
return 'Tuesday';
case 3:
return 'Wednesday';
case 4:
return 'Thursday';
case 5:
return 'Friday';
case 6:
return 'Saturday';
case 7:
return 'Sunday';
}
}
assert.equal(dayOfTheWeek(5), 'Friday');return oder break!Am Ende einer case-Klausel wird die Ausführung mit der nächsten case-Klausel fortgesetzt, es sei denn, wir return oder break – zum Beispiel
function englishToFrench(english) {
let french;
switch (english) {
case 'hello':
french = 'bonjour';
case 'goodbye':
french = 'au revoir';
}
return french;
}
// The result should be 'bonjour'!
assert.equal(englishToFrench('hello'), 'au revoir');Das heißt, unsere Implementierung von dayOfTheWeek() funktionierte nur, weil wir return verwendet haben. Wir können englishToFrench() reparieren, indem wir break verwenden
function englishToFrench(english) {
let french;
switch (english) {
case 'hello':
french = 'bonjour';
break;
case 'goodbye':
french = 'au revoir';
break;
}
return french;
}
assert.equal(englishToFrench('hello'), 'bonjour'); // okcase-KlauselnDie Anweisungen einer case-Klausel können weggelassen werden, was uns effektiv mehrere case-Ausdrücke pro case-Klausel gibt
function isWeekDay(name) {
switch (name) {
case 'Monday':
case 'Tuesday':
case 'Wednesday':
case 'Thursday':
case 'Friday':
return true;
case 'Saturday':
case 'Sunday':
return false;
}
}
assert.equal(isWeekDay('Wednesday'), true);
assert.equal(isWeekDay('Sunday'), false);default-KlauselEine default-Klausel wird angesprungen, wenn der switch-Ausdruck keine andere Übereinstimmung hat. Das macht sie nützlich für die Fehlerprüfung
function isWeekDay(name) {
switch (name) {
case 'Monday':
case 'Tuesday':
case 'Wednesday':
case 'Thursday':
case 'Friday':
return true;
case 'Saturday':
case 'Sunday':
return false;
default:
throw new Error('Illegal value: '+name);
}
}
assert.throws(
() => isWeekDay('January'),
{message: 'Illegal value: January'}); Übungen:
switch
exercises/control-flow/number_to_month_test.mjs
exercises/control-flow/is_object_via_switch_test.mjswhile-Schleifen [ES1]Eine while-Schleife hat den folgenden Aufbau
while («condition») {
«statements»
}
Vor jeder Schleifeniteration wertet while die condition aus
while-Körper einmal mehr ausgeführt.while-SchleifenDer folgende Code verwendet eine while-Schleife. In jeder Schleifeniteration entfernt er das erste Element von arr mit .shift() und gibt es aus.
const arr = ['a', 'b', 'c'];
while (arr.length > 0) {
const elem = arr.shift(); // remove first element
console.log(elem);
}
// Output:
// 'a'
// 'b'
// 'c'Wenn die Bedingung immer zu true ausgewertet wird, ist while eine Endlosschleife
while (true) {
if (Math.random() === 0) break;
}do-while-Schleifen [ES3]Die do-while-Schleife funktioniert ähnlich wie while, aber sie prüft ihre Bedingung nach jeder Schleifeniteration, nicht davor.
let input;
do {
input = prompt('Enter text:');
console.log(input);
} while (input !== ':q');do-while kann auch als while-Schleife betrachtet werden, die mindestens einmal durchläuft.
prompt() ist eine globale Funktion, die in Webbrowsern verfügbar ist. Sie fordert den Benutzer auf, Text einzugeben und gibt ihn zurück.
for-Schleifen [ES1]Eine for-Schleife hat den folgenden Aufbau
for («initialization»; «condition»; «post_iteration») {
«statements»
}
Die erste Zeile ist der Kopf der Schleife und steuert, wie oft der Körper (der Rest der Schleife) ausgeführt wird. Er hat drei Teile, und jeder davon ist optional
initialization: Richtet Variablen usw. für die Schleife ein. Variablen, die hier mit let oder const deklariert werden, existieren nur innerhalb der Schleife.condition: Diese Bedingung wird vor jeder Schleifeniteration geprüft. Wenn sie falsy ist, stoppt die Schleife.post_iteration: Dieser Code wird nach jeder Schleifeniteration ausgeführt.Eine for-Schleife ist daher ungefähr äquivalent zur folgenden while-Schleife
«initialization»
while («condition») {
«statements»
«post_iteration»
}
for-SchleifenAls Beispiel hier, wie man mit einer for-Schleife von Null bis Zwei zählt
for (let i=0; i<3; i++) {
console.log(i);
}
// Output:
// 0
// 1
// 2So gibt man den Inhalt eines Arrays mit einer for-Schleife aus
const arr = ['a', 'b', 'c'];
for (let i=0; i<arr.length; i++) {
console.log(arr[i]);
}
// Output:
// 'a'
// 'b'
// 'c'Wenn wir alle drei Teile des Kopfes weglassen, erhalten wir eine Endlosschleife
for (;;) {
if (Math.random() === 0) break;
}for-of-Schleifen [ES6]Eine for-of-Schleife iteriert über jedes iterable – ein Datencontainer, der das Iterationsprotokoll unterstützt. Jeder iterierte Wert wird in einer Variablen gespeichert, wie im Kopf angegeben
for («iteration_variable» of «iterable») {
«statements»
}
Die Iterationsvariable wird normalerweise über eine Variablendeklaration erstellt
const iterable = ['hello', 'world'];
for (const elem of iterable) {
console.log(elem);
}
// Output:
// 'hello'
// 'world'Aber wir können auch eine (veränderliche) Variable verwenden, die bereits existiert
const iterable = ['hello', 'world'];
let elem;
for (elem of iterable) {
console.log(elem);
}const: for-of vs. forBeachten Sie, dass wir in for-of-Schleifen const verwenden können. Die Iterationsvariable kann für jede Iteration immer noch unterschiedlich sein (sie kann nur während der Iteration nicht geändert werden). Stellen Sie es sich wie eine neue const-Deklaration vor, die jedes Mal in einem neuen Gültigkeitsbereich ausgeführt wird.
Im Gegensatz dazu müssen wir in for-Schleifen Variablen über let oder var deklarieren, wenn sich ihre Werte ändern.
Wie bereits erwähnt, funktioniert for-of mit jedem iterable Objekt, nicht nur mit Arrays – zum Beispiel mit Sets
const set = new Set(['hello', 'world']);
for (const elem of set) {
console.log(elem);
}Zuletzt können wir for-of auch verwenden, um über die [Index, Element]-Einträge von Arrays zu iterieren
const arr = ['a', 'b', 'c'];
for (const [index, elem] of arr.entries()) {
console.log(`${index} -> ${elem}`);
}
// Output:
// '0 -> a'
// '1 -> b'
// '2 -> c'Mit [index, element] verwenden wir Destrukturierung, um auf Array-Elemente zuzugreifen.
Übung:
for-of
exercises/control-flow/array_to_string_test.mjs
for-await-of-Schleifen [ES2018]for-await-of ist wie for-of, aber es arbeitet mit asynchronen Iterables statt mit synchronen. Und es kann nur innerhalb von asynchronen Funktionen und asynchronen Generatoren verwendet werden.
for await (const item of asyncIterable) {
// ···
}for-await-of wird detailliert im Kapitel über asynchrone Iteration beschrieben.
for-in-Schleifen (vermeiden) [ES1]Die for-in-Schleife durchläuft alle (eigenen und geerbten) aufzählbaren Eigenschaftsschlüssel eines Objekts. Beim Schleifen über ein Array ist sie selten eine gute Wahl
Der folgende Code demonstriert diese Punkte
const arr = ['a', 'b', 'c'];
arr.propKey = 'property value';
for (const key in arr) {
console.log(key);
}
// Output:
// '0'
// '1'
// '2'
// 'propKey'for-await-of verwenden.for-of verwenden. Beachten Sie, dass Arrays Iterables sind..forEach() verwenden.for-Schleife verwenden, um über ein Array zu iterieren.for-in nicht, um über ein Array zu iterieren. Quiz
Siehe Quiz-App.