Labels sind ein Feature, das seit der Erfindung von JavaScript existiert. Sie sind nicht neu! Ich glaube nicht, dass viele Leute davon wissen, und ich würde sogar behaupten, dass sie ein wenig verwirrend sind. Aber, wie wir sehen werden, können Labels in sehr spezifischen Fällen nützlich sein.
Aber zuerst: Ein JavaScript-Label sollte nicht mit einem HTML-<label> verwechselt werden, was etwas völlig anderes ist!
Ein JavaScript-Label ist eine Möglichkeit, eine Anweisung oder einen Codeblock zu benennen. Typischerweise: Schleifen und bedingte Anweisungen. Das ermöglicht es Ihnen, die beschriftete Anweisung von innen heraus mit break oder continue zu beenden. Um einer Anweisung ein Label zuzuweisen, beginnen Sie die Anweisung mit label: und was auch immer Sie als "Label" angeben, wird das Label sein, auf das Sie später verweisen können.
Hier ist die grundlegende Syntax für ein Label
let x = 0;
// Label a loop as "myLoop"
myLoop:
while (true) {
if (x >= 10) {
// This will cause "myLoop" to end.
break myLoop;
}
x++;
}
Labels sind nur eine interne Referenz auf eine Anweisung und können nicht nachgeschlagen, exportiert oder in einem Wert gespeichert werden. Sie kollidieren auch nicht mit Variablennamen, sodass Sie, wenn Sie die Leute wirklich verwirren wollen, eine Schleife und eine Variable denselben Namen geben können! Bitte tun Sie das nicht – Ihr zukünftiges Ich und jeder andere, der Ihren Code lesen muss, wird es Ihnen danken. Die Anwendungsfälle für Labels sind begrenzt, aber in den richtigen Händen unglaublich leistungsstark.
Eine kurze Einführung in break und continue
Lassen Sie uns ein wenig zurückgehen und über break und continue sprechen. Eine break-Anweisung beendet die aktuell laufende Schleife oder bedingte Anweisung. Sie wird am häufigsten in einer switch-Anweisung verwendet, um einen case zu beenden, kann aber auch verwendet werden, um eine if-Anweisung frühzeitig zu beenden oder auch um eine for- oder while-Schleife zu beenden und die Schleifen zu stoppen. Es ist eine gute Möglichkeit, aus einer bedingten Anweisung auszubrechen oder eine Schleife frühzeitig zu beenden.
Hier ist ein einfaches Beispiel für break in Aktion
const x = 1;
switch(x) {
case 1:
console.log('On your mark!');
break; // Doesn't check the rest of the switch statement if 1 is true
case 2:
console.log('Get set!');
break; // Doesn't check the rest of the switch statement if 2 is true
case 3:
console.log('GO!');
break; // Doesn't check the rest of the switch statement if 3 is true
}
// logs: 'On your mark!'
Ähnlich kann die continue-Anweisung mit Schleifen verwendet werden, um die aktuelle Iteration frühzeitig zu beenden und den nächsten Durchlauf der Schleife zu starten. Dies funktioniert jedoch nur innerhalb von Schleifen.
Hier ist continue in Aktion
for (let x = 0; x &< 10; x++) {
if (x !== 5) continue; // If the number isn't five, go to the next pass of the loop.
console.log(x);
}
// logs: 5
Verwendung eines Labels mit break
Typischerweise taucht ein Anwendungsfall für Labels auf, wenn Sie verschachtelte Anweisungen jeglicher Art verwenden. Die Verwendung mit break kann eine tief verschachtelte Schleife oder Bedingung stoppen und sofort beenden.
Kommen wir zum Titel dieses Blogbeitrags!
// Our outer if statement
outerIf:
if (true) {
// Our inner if statement
innerIf:
if (true) {
break outerIf; // Immediately skips to the end of the outer if statement
}
console.log('This never logs!');
}
Da haben Sie es, Sie können eine if-Anweisung mit einem Label versehen.
Verwendung eines Labels mit continue
Es gab Zeiten, in denen ich eine verschachtelte Schleife erstellt habe und einige Iterationen der äußeren Schleife überspringen wollte, während ich mich in der inneren Schleife befand. Normalerweise breche ich die innere Schleife ab, prüfe dann, ob ich mich in dem Zustand befinde, den ich überspringen möchte, und fahre dann mit der äußeren Schleife fort. Die Möglichkeit, diesen Code in eine leichter lesbare Anweisung zu vereinfachen, ist großartig!
let x = 0;
outerLoop:
while (x < 10) {
x++;
for (let y = 0; y < x; y++) {
// This will jump back to the top of outerLoop
if (y === 5) continue outerLoop;
console.log(x,y);
}
console.log('----'); // This will only happen if x < 6
}
Block-Anweisungen und Labels
Block-Anweisungen in JavaScript sind eine Möglichkeit, Ihre const- und let-Variablen auf einen Teil Ihres Codes zu beschränken. Das kann nützlich sein, wenn Sie einige Variablen lokalisieren möchten, ohne eine Funktion erstellen zu müssen. Die (große) Einschränkung dabei ist, dass Block-Anweisungen im strict mode ungültig sind, was ES-Module standardmäßig sind.
Hier ist eine beschriftete Block-Anweisung
// This example throws a syntax error in an ES module
const myElement = document.createElement('p');
myConditionalBlock: {
const myHash = window.location.hash;
// escape the block if there is not a hash.
if (!myHash) break myConditionalBlock;
myElement.innerText = myHash;
}
console.log(myHash); // undefined
document.body.appendChild(myElement);
Praktische Anwendung
Es hat eine Weile gedauert, bis ich einen Grund gefunden habe, ein Label im alltäglichen Produktionscode zu verwenden. Das mag ein wenig weit hergeholt sein, aber ein Bereich, in dem ein Label in JavaScript nützlich sein könnte, ist das frühe Verlassen einer Schleife innerhalb einer switch-Anweisung. Da man in einem switch break verwenden kann, könnte die Möglichkeit, einer Schleife ein Label zuzuweisen, das sie frühzeitig beendet, potenziell Ihren Code effizienter machen.
Hier ist, wie wir das in einer Taschenrechner-App verwenden könnten
const calculatorActions = [
{ action: "ADD", amount: 1 },
{ action: "SUB", amount: 5 },
{ action: "EQ" },
{ action: "ADD", amount: 10 }
];
let el = {};
let amount = 0;
calculate: while (el) {
// Remove the first element of the calculatorActions array
el = calculatorActions.shift();
switch (el.action) {
case "ADD":
amount += el.amount;
break; // Breaks the switch
case "SUB":
amount -= el.amount;
break; // Breaks the switch
case "EQ":
break calculate; // Breaks the loop
default:
continue calculate; // If we have an action we don't know, skip it.
}
}
Auf diese Weise können wir die calculate-Schleife verlassen, wenn eine Bedingung erfüllt ist, anstatt das Skript weiterlaufen zu lassen!
Fazit
Es ist selten, dass Sie ein JavaScript-Label verwenden müssen. Tatsächlich können Sie ein sehr erfülltes Berufsleben führen, ohne jemals zu wissen, dass dies existiert. Aber für den unwahrscheinlichen Fall, dass Sie *diesen einen* Ort finden, an dem diese Syntax hilfreich ist, sind Sie jetzt befähigt, sie zu nutzen.
also im Grunde wie eine goto-Anweisung in anderen Sprachen…
Vielleicht? Außer dass es nirgendwo hingeht?
Was für ein interessantes Feature. Das wusste ich noch nie.
Außerdem legt dieser Teil
break outerIf; // Überspringt sofort das Ende der äußeren if-Anweisungnahe, dass es tatsächlich irgendwo hingeht.breakgeht nach vorne undcontinuegeht zurück. Es ist nicht so flexibel wie eine tatsächlichegoto-Anweisung, aber ich sehe, wie die Abhängigkeit davon zu Spaghetticode führen könnte.Es ist ein ziemlich begrenztes und spezialisiertes
goto, das immer noch an die logische Codestruktur gebunden ist, nicht wie das uneingeschränktegotoeiniger anderer Sprachen.Die Verwendung von
breakin einerswitch-Anweisung ist in einigen Sprachen Standard, damit ist nichts falsch.Der andere "normale" Verwendungszweck für
breakin JS, und sicherlich der einzige Nicht-switch-Verwendungszweck, den ich je gemacht habe (und das nur *sehr* gelegentlich), ist, dass eine verschachtelte innere Schleife die äußere Schleifebreakodercontinue– dies kann zu saubererem und leichter verständlichem Code führen, als zu versuchen, dieselbe Logik mit mehrif/else-Strukturen oder Ähnlichem zu erreichen.Ich habe noch nie ein
breakaus einemif-Block heraus benötigt oder gewollt, wie der Artikel es vorschlug.Dieses Feature ist sicherlich eines dieser Dinge, bei denen man es *könnte*, aber es ist wahrscheinlich die Verwirrung und/oder Angst, die es bei anderen Entwicklern auslösen würde, nicht wert!
Labels und "goto" sind dasselbe. Sie zielen darauf ab, der Laufzeitumgebung mitzuteilen, dass sie ihren linearen Ablauf überspringen muss. Dieses Verhalten kann gefährlich sein, wenn man versucht, den Code zur Laufzeit zu verfolgen. Es führt zu seltsamen Fehlern und Problemen.
Und meiner Meinung nach wird der Code durch die Verwendung von Labels (oder gotos) weniger lesbar.
Fast alle Sprachen ermutigen dazu, die Verwendung zu vermeiden.
Es gibt keinen Grund, zu solchen Anweisungen zurückzukehren.
Intern ist dies das, was in allen modernen High-Level-Sprachen abstrahiert wurde, aber es gibt wirklich nichts Falsches an diesem Ansatz, wenn man ein solides Verständnis von Low-Level-Sprachen hat.
Es ist Standardverwendung in einem
switch.Und es ist in einigen Fällen in Ordnung, wenn eine verschachtelte innere Schleife die äußere Schleife
breakodercontinue– dies kann zu saubererem und leichter verständlichem Code führen, als zu versuchen, dieselbe Logik mit mehrif/else-Strukturen oder verschachtelten Funktionsaufrufen mit bedingtenreturns oder Ähnlichem zu erreichen.Aber andere Verwendungen von
breakmachen den Code nur verwirrender. (Aus einemif-Block ausbrechen? Tun Sie es einfach nicht.)Man kann, aber bitte nicht!
Der Autor hätte tiefer darauf eingehen sollen, wie "continue" innerhalb einer verschachtelten Schleife funktioniert.
Wenn Sie mit dem äußeren Label innerhalb einer inneren Schleife "continue" verwenden, bricht dies tatsächlich aus allen inneren Schleifen aus, bis es die äußere Schleife erreicht, die mit dem Label übereinstimmt, und dann mit der nächsten Iteration dieser äußeren Schleife "fortfährt". "Continue" ist also effektiv "break" für diejenigen Schleifen, bei denen es nicht mit dem Label übereinstimmt.
Beispiel –
Hier bricht
continue labelAaus der Schleife von labelB aus, setzt aber die nächste Iteration der Schleife von labelA fort.häh? ich habe es gerade in meiner Konsole überprüft – sowohl unbeschriftete als auch beschriftete Block-Anweisungen funktionieren in beiden Modi einwandfrei. Ich habe das auch nicht auf MDN gesehen.
(auch fast jedes let/const Tutorial verwendet Block-Anweisungen, um Block-Scoping zu demonstrieren)
Oh, hallo! Sie haben Recht. Ich dachte, ich hätte das getestet, aber ich war eindeutig verwirrt. Die MDN-Dokumente sagen Folgendes:
Interessant.
breakinif ()-Anweisungen und Block-Anweisungen hat meiner Meinung nach durchaus einige gültige Anwendungsfälle.Ich glaube jedoch nicht, dass Sie Recht haben, dass beschriftete Block-Anweisungen im strict mode ungültig sind. Dies funktioniert wie erwartet in NodeJS (auch in ESM).
Schön! Eine Frage... Thema und Schriftart? Vscode?
Im letzten Beispiel gibt es einen Fehler. Wenn calculatedActions leer ist und el calculatorActions.shift(); undefined zurückgibt, wird die nächste Zeile einen Fehler auslösen.
Das sieht so falsch aus...
In PHP verwendet man einfach break n (wobei n eine natürliche Zahl ist), um aus verschachtelten Schleifen oder Switches innerhalb von Schleifen auszubrechen.
Lasst uns den Hauptanwendungsfall für Labels in JavaScript, der derzeit existiert, nicht ignorieren – Svelte verwendet das
$-Label für seine Reaktivitätslogik!Das ist schlichtweg falsch. Können wir den Artikel aktualisieren?