Читать книгу JavaScript – Das Handbuch für die Praxis - David Flanagan - Страница 27
2.6Optionale Semikola
ОглавлениеWie viele andere Programmiersprachen verwendet auch JavaScript das Semikolon (;) zur Trennung von Anweisungen (siehe Kapitel 5). Das ist wichtig, um die Bedeutung Ihres Codes klarzustellen: Ohne Trennzeichen könnte das Ende einer Anweisung als Anfang der nächsten interpretiert werden oder umgekehrt. Normalerweise können Sie in JavaScript das Semikolon zwischen zwei Anweisungen weglassen, wenn diese Anweisungen in getrennten Zeilen stehen. (Am Ende eines Programms ist ebenfalls kein Semikolon vorgeschrieben. Das Gleiche gilt, wenn das folgende Token in einem Programm eine schließende geschweifte Klammer (}) ist.) Viele JavaScript-Programmierer (und ich im Code dieses Buchs) verwenden Semikola, um explizit das Ende von Anweisungen zu markieren, auch wenn es an diesen Stellen eigentlich nicht nötig ist. Bei einer anderen stilistischen Variante werden Semikola nach Möglichkeit weggelassen und nur in den wenigen Situationen verwendet, in denen sie tatsächlich vorgeschrieben sind. Für welche dieser Varianten Sie sich auch entscheiden – es gibt einige Auswirkungen optionaler Semikola, die Sie kennen sollten.
Betrachten Sie den folgenden Code. Da die beiden Anweisungen in zwei separaten Zeilen stehen, könnten Sie das erste Semikolon weglassen:
a = 3;
b = 4;
Schreibt man die Anweisungen jedoch folgendermaßen, ist das erste Semikolon unbedingt erforderlich:
a = 3; b = 4;
Beachten Sie bitte, dass JavaScript nicht jeden Zeilenumbruch als Semikolon behandelt: Das passiert normalerweise nur, wenn es den Code nicht parsen kann, ohne ein implizites Semikolon hinzuzufügen. Formeller ausgedrückt (und mit drei Ausnahmen, die etwas später beschrieben werden): JavaScript behandelt einen Zeilenumbruch als Semikolon, wenn das nächste Nicht-Leerzeichen nicht als Fortsetzung der aktuellen Anweisung interpretiert werden kann. Betrachten Sie diesen Code:
let a
a
=
3
console.log(a)
JavaScript interpretiert ihn folgendermaßen:
let a; a = 3; console.log(a);
JavaScript behandelt den ersten Zeilenumbruch als Semikolon, weil es den Code let a a ohne Semikolon nicht parsen kann. Das zweite a könnte allerdings auch als eigenständige Anweisung a; interpretiert werden. JavaScript behandelt den zweiten Zeilenumbruch jedoch nicht als Semikolon, weil es die längere Anweisung a = 3; weiter parsen kann.
Diese Regeln, anhand deren das Ende von Anweisungen erkannt wird, können zu einigen überraschenden Situationen führen. Folgender Code scheint aus zwei eigenständigen Anweisungen zu bestehen, die durch einen Zeilenumbruch getrennt werden:
let y = x + f
(a+b).toString()
Die Klammern zu Beginn der zweiten Zeile können aber auch als ein Funktionsaufruf auf dem f-Element der ersten Zeile interpretiert werden, sodass JavaScript den Code folgendermaßen lesen würde:
let y = x + f(a+b).toString();
Es ist ziemlich unwahrscheinlich, dass eine solche Interpretation beabsichtigt ist. Hier ist also explizit ein Semikolon erforderlich, damit die Anweisungen tatsächlich separat behandelt werden.
Allgemein kann man sagen: Wenn eine Anweisung mit (, [, /, + oder - beginnt, besteht die Möglichkeit, dass sie als Fortsetzung der vorherigen Anweisung interpretiert wird. Anweisungen, die mit /, + oder - beginnen, sind in der Praxis recht selten, aber Anweisungen, die mit ( und [ beginnen, sind – zumindest in einigen JavaScript-Programmierstilen – keineswegs ungewöhnlich. Manche Programmierer stellen derartigen Anweisungen zur Sicherheit ein Semikolon voran, damit der Code auch dann noch korrekt funktioniert, wenn die vorhergehende Anweisung abgeändert und ein eventuell zuvor vorhandenes abschließendes Semikolon entfernt wird:
let x = 0 // Semikolon hier weggelassen.
;[x,x+1,x+2].forEach(console.log) // Ein "defensives" Semikolon sorgt für
// die sichere Trennung der Anweisungen.
Es gibt drei Ausnahmen von der allgemeinen Regel, dass JavaScript Zeilenumbrüche als Semikolon interpretiert, wenn es die zweite Zeile nicht als Fortsetzung der Anweisung der ersten Zeile parsen kann. Die erste Ausnahme betrifft die Anweisungen return, throw, yield, break und continue (siehe Kapitel 5). Diese Anweisungen stehen häufig allein, manchmal aber folgt auf sie ein Identifier oder Ausdruck. Folgt nach einem dieser Wörter (vor irgendwelchen weiteren Tokens) ein Zeilenumbruch, interpretiert JavaScript diesen Zeilenumbruch immer als Semikolon. Schreiben Sie beispielsweise
return
true;
geht JavaScript davon aus, dass Sie Folgendes meinen:
return; true;
Wahrscheinlich haben Sie aber eher dies im Sinn gehabt:
return true;
Das bedeutet, dass Sie keinen Zeilenumbruch zwischen return, break oder continue und dem Ausdruck einfügen dürfen, der dem Schlüsselwort folgt. Machen Sie es trotzdem, wird die Ausführung Ihres Codes vermutlich fehlschlagen – und zwar auf eine Weise, die nur schwer zu durchschauen oder zu debuggen ist.
Die zweite Ausnahme betrifft die Operatoren ++ und -- (siehe 4.8). Diese Operatoren können als Präfixoperatoren vor oder als Postfixoperatoren nach einem Ausdruck eingesetzt werden. Möchten Sie einen dieser Operatoren als Postfixoperator benutzen, muss er in der gleichen Zeile stehen wie der Ausdruck, auf den er angewandt werden soll. Die dritte Ausnahme betrifft Funktionen, die mit der kompakten Pfeilnotation definiert sind: Der =>-Pfeil selbst muss in derselben Zeile wie die Parameterliste stehen.