Dieser Inhalt wurde automatisch aus dem Englischen übersetzt, und kann Fehler enthalten. Erfahre mehr über dieses Experiment.

View in English Always switch to English

Lexikalische Grammatik

Diese Seite beschreibt die lexikalische Grammatik von JavaScript. Der JavaScript-Quelltext ist einfach eine Folge von Zeichen – damit der Interpreter ihn verstehen kann, muss die Zeichenkette in eine strukturiertere Darstellung geparst werden. Der erste Schritt des Parsens wird lexikalische Analyse genannt, bei der der Text von links nach rechts gescannt und in eine Folge von einzelnen, atomaren Eingabeelementen umgewandelt wird. Einige Eingabeelemente sind für den Interpreter unbedeutend und werden nach diesem Schritt entfernt – dazu gehören Leerzeichen und Kommentare. Die anderen, einschließlich Bezeichner, Schlüsselwörter, Literale und Interpunktionszeichen (meistens Operatoren), werden für die weitere Syntaxanalyse verwendet. Zeilentrennzeichen und mehrzeilige Kommentare sind auch syntaktisch unbedeutend, aber sie leiten den Prozess der automatischen Einfügung von Semikolons, um bestimmte ungültige Tokenfolgen gültig zu machen.

Formatsteuerzeichen

Formatsteuerzeichen haben keine visuelle Darstellung, werden jedoch verwendet, um die Interpretation des Textes zu steuern.

Codepunkt Name Abkürzung Beschreibung
U+200C Zero width non-joiner <ZWNJ> Zwischen Zeichen eingefügt, um zu verhindern, dass sie in bestimmten Sprachen zu Ligaturen verbunden werden (Wikipedia).
U+200D Zero width joiner <ZWJ> Zwischen Zeichen eingefügt, die normalerweise nicht verbunden werden, um zu bewirken, dass die Zeichen in bestimmten Sprachen in verbundener Form dargestellt werden (Wikipedia).
U+FEFF Byte order mark <BOM> Wird am Anfang des Skripts verwendet, um es als Unicode zu kennzeichnen und die Erkennung der Textkodierung und der Byte-Reihenfolge zu ermöglichen (Wikipedia).

Im JavaScript-Quelltext werden <ZWNJ> und <ZWJ> als Bezeichner-Teile behandelt, während <BOM> (auch als Zero-Width No-Break Space <ZWNBSP> bezeichnet, wenn es nicht am Anfang des Textes steht) als Leerzeichen behandelt wird.

Leerzeichen

Leerzeichen-Zeichen verbessern die Lesbarkeit des Quelltexts und trennen Tokens voneinander. Diese Zeichen sind in der Regel für die Funktionalität des Codes unnötig. Minifizierungstools werden häufig verwendet, um Leerzeichen zu entfernen, um die Datenmenge zu reduzieren, die übertragen werden muss.

Codepunkt Name Abkürzung Beschreibung Escape-Sequenz
U+0009 Charaktertabulator <TAB> Horizontale Tabulation \t
U+000B Linientabulation <VT> Vertikale Tabulation \v
U+000C Seitenvorschub <FF> Seitenumbruch-Steuerzeichen (Wikipedia). \f
U+0020 Leerzeichen <SP> Normales Leerzeichen
U+00A0 Untrennbares Leerzeichen <NBSP> Normales Leerzeichen, aber kein Punkt, an dem eine Zeile gebrochen werden darf
U+FEFF Zero-width no-break space <ZWNBSP> Wenn nicht am Anfang eines Skripts, ist das BOM-Marker ein normales Leerzeichen-Charakter.
Andere Andere Unicode-Leerzeichen <USP> Charaktere in der "Space_Separator" allgemeinen Kategorie

Hinweis: Von diesen Zeichen mit der Eigenschaft „White_Space“, die aber nicht in der allgemeinen Kategorie "Space_Separator" sind werden U+0009, U+000B und U+000C in JavaScript immer noch als Leerzeichen behandelt; U+0085 NEXT LINE hat keine besondere Rolle; andere werden zum Satz der Zeilentrennzeichen.

Hinweis: Änderungen am Unicode-Standard, der von der JavaScript-Engine verwendet wird, können das Verhalten von Programmen beeinflussen. Zum Beispiel hat das ES2016 den Referenz-Unicode-Standard von 5.1 auf 8.0.0 aktualisiert, wodurch U+180E MONGOLISCHER VOKAL-TRENNER aus der Kategorie „Space_Separator“ in die Kategorie „Format (Cf)“ verschoben wurde und nicht mehr als Leerzeichen behandelt wird. Folglich änderte sich das Ergebnis von "\u180E".trim().length von 0 auf 1.

Zeilentrennzeichen

Zusätzlich zu Leerzeichen-Zeichen werden auch Zeilentrennzeichen zur Verbesserung der Lesbarkeit des Quelltexts verwendet. In einigen Fällen können Zeilentrennzeichen die Ausführung von JavaScript-Code beeinflussen, da es einige Stellen gibt, an denen sie verboten sind. Zeilentrennzeichen beeinflussen auch den Prozess der automatischen Einfügung von Semikolons.

Außerhalb des Kontexts der lexikalischen Grammatik werden Leerzeichen und Zeilentrennzeichen oft vermischt. Zum Beispiel entfernt String.prototype.trim() alle Leerzeichen und Zeilentrennzeichen vom Anfang und Ende eines Strings. Die \s Zeichenklassen-Escape in regulären Ausdrücken entsprechen allen Leerzeichen und Zeilentrennzeichen.

Nur die folgenden Unicode-Codepunkte werden in ECMAScript als Zeilentrennzeichen behandelt, andere Zeichen, die Zeilen brechen, werden als Leerzeichen behandelt (zum Beispiel wird das Zeichen Next Line, NEL, U+0085 als Leerzeichen betrachtet).

Codepunkt Name Abkürzung Beschreibung Escape-Sequenz
U+000A Zeilenumbruch <LF> Neues Zeilenzeichen in UNIX-Systemen. \n
U+000D Wagenrücklauf <CR> Neues Zeilenzeichen in Commodore- und frühen Mac-Systemen. \r
U+2028 Zeilentrenner <LS> Wikipedia
U+2029 Absatztrenner <PS> Wikipedia

Kommentare

Kommentare werden verwendet, um Hinweise, Notizen, Vorschläge oder Warnungen im JavaScript-Code hinzuzufügen. Dies kann es leichter machen, den Code zu lesen und zu verstehen. Sie können auch verwendet werden, um Code zu deaktivieren, um zu verhindern, dass er ausgeführt wird; dies kann ein wertvolles Debugging-Tool sein.

JavaScript bietet zwei traditionsreiche Methoden, um Kommentare zum Code hinzuzufügen: Zeilenkommentare und Blockkommentare. Zusätzlich gibt es eine spezielle Hashbang-Kommentar-Syntax.

Zeilenkommentare

Die erste Methode ist der //-Kommentar; dieser macht den gesamten folgenden Text in derselben Zeile zu einem Kommentar. Zum Beispiel:

js
function comment() {
  // This is a one line JavaScript comment
  console.log("Hello world!");
}
comment();

Blockkommentare

Die zweite Methode ist der /* */-Stil, der wesentlich flexibler ist.

Zum Beispiel können Sie es in einer einzigen Zeile verwenden:

js
function comment() {
  /* This is a one line JavaScript comment */
  console.log("Hello world!");
}
comment();

Sie können auch mehrzeilige Kommentare machen, wie dieser:

js
function comment() {
  /* This comment spans multiple lines. Notice
     that we don't need to end the comment until we're done. */
  console.log("Hello world!");
}
comment();

Sie können es auch in der Mitte einer Zeile verwenden, wenn Sie möchten, obwohl dies Ihren Code schwerer lesbar machen kann, daher sollte es mit Vorsicht verwendet werden:

js
function comment(x) {
  console.log("Hello " + x /* insert the value of x */ + " !");
}
comment("world");

Darüber hinaus können Sie es verwenden, um Code zu deaktivieren, um zu verhindern, dass er ausgeführt wird, indem Sie den Code in einem Kommentar einbetten, wie dies:

js
function comment() {
  /* console.log("Hello world!"); */
}
comment();

In diesem Fall wird der console.log()-Aufruf nie ausgeführt, da er sich in einem Kommentar befindet. Auf diese Weise können beliebig viele Zeilen Code deaktiviert werden.

Blockkommentare, die mindestens ein Zeilentrennzeichen enthalten, verhalten sich wie Zeilentrennzeichen in der automatischen Einfügung von Semikolons.

Hashbang-Kommentare

Es gibt eine spezielle dritte Kommentarsyntax, den Hashbang-Kommentar. Ein Hashbang-Kommentar verhält sich genau wie ein Einzelzeilen-(//)-Kommentar, außer dass er mit #! beginnt und nur am absoluten Beginn eines Skripts oder Moduls gültig ist. Beachten Sie auch, dass vor dem #! keinerlei Leerzeichen erlaubt sind. Der Kommentar besteht aus allen Zeichen nach #! bis zum Ende der ersten Zeile; es ist nur ein solcher Kommentar erlaubt.

Hashbang-Kommentare in JavaScript ähneln Shebangs in Unix, die den Pfad zu einem spezifischen JavaScript-Interpreter angeben, den Sie verwenden möchten, um das Skript auszuführen. Bevor der Hashbang-Kommentar standardisiert wurde, war er bereits de-facto bei nicht-browserbasierten Hosts wie Node.js implementiert, wo er aus dem Quelltext entfernt wurde, bevor er an die Engine übergeben wurde. Ein Beispiel ist wie folgt:

js
#!/usr/bin/env node

console.log("Hello world");

Der JavaScript-Interpreter behandelt ihn als normalen Kommentar – er hat nur eine semantische Bedeutung für die Shell, wenn das Skript direkt in einer Shell ausgeführt wird.

Warnung: Wenn Sie möchten, dass Skripte direkt in einer Shell-Umgebung ausgeführt werden können, kodieren Sie sie in UTF-8 ohne eine BOM. Obwohl ein BOM keine Probleme für Code verursacht, der in einem Browser läuft – da es während der UTF-8-Decodierung entfernt wird, bevor der Quelltext analysiert wird – erkennt eine Unix/Linux-Shell den Hashbang nicht, wenn er von einem BOM-Zeichen vorangestellt ist.

Sie dürfen den #!-Kommentartyp nur verwenden, um einen JavaScript-Interpreter anzugeben. In allen anderen Fällen verwenden Sie einfach einen //-Kommentar (oder einen mehrzeiligen Kommentar).

Bezeichner

Ein Bezeichner wird verwendet, um einen Wert mit einem Namen zu verknüpfen. Bezeichner können an verschiedenen Stellen verwendet werden:

js
const decl = 1; // Variable declaration (may also be `let` or `var`)
function fn() {} // Function declaration
const obj = { key: "value" }; // Object keys
// Class declaration
class C {
  #priv = "value"; // Private field
}
lbl: console.log(1); // Label

In JavaScript bestehen Bezeichner in der Regel aus alphanumerischen Zeichen, Unterstrichen (_) und Dollarzeichen ($). Bezeichner dürfen nicht mit Zahlen beginnen. Jedoch sind JavaScript-Bezeichner nicht nur auf ASCII beschränkt – viele Unicode-Codepunkte sind ebenfalls erlaubt. Namentlich:

  • Startzeichen können jedes Zeichen in der ID_Start Kategorie plus _ und $ sein.
  • Nach dem ersten Zeichen können Sie jedes Zeichen in der ID_Continue Kategorie plus U+200C (ZWNJ) und U+200D (ZWJ) verwenden.

Hinweis: Wenn Sie aus irgendeinem Grund JavaScript-Quelltext selbst parsen müssen, gehen Sie nicht davon aus, dass alle Bezeichner dem Muster /[A-Za-z_$][\w$]*/ (d.h. nur ASCII)! Der Bereich der Bezeichner kann durch den regulären Ausdruck /[$_\p{ID_Start}][$\p{ID_Continue}]*/u (ohne Unicode-Escape-Sequenzen) beschrieben werden.

Darüber hinaus erlaubt JavaScript die Verwendung von Unicode-Escape-Sequenzen in der Form von \u0000 oder \u{000000} in Bezeichnern, die denselben Zeichenfolgenwert wie die tatsächlichen Unicode-Zeichen codieren. Zum Beispiel sind 你好 und \u4f60\u597d die gleichen Bezeichner:

js
const 你好 = "Hello";
console.log(\u4f60\u597d); // Hello

Nicht alle Stellen akzeptieren den vollen Umfang der Bezeichner. Bestimmte Syntaxen, wie Funktionsdeklarationen, Funktionsausdrücke und Variablendeklarationen, setzen die Verwendung von Bezeichnernamen voraus, die keine reservierten Wörter sind.

js
function import() {} // Illegal: import is a reserved word.

Am bemerkenswertesten ist, dass private Elemente und Objekteigenschaften reservierte Wörter erlauben.

js
const obj = { import: "value" }; // Legal despite `import` being reserved
class C {
  #import = "value";
}

Schlüsselwörter

Schlüsselwörter sind Tokens, die wie Bezeichner aussehen, aber besondere Bedeutungen in JavaScript haben. Beispielsweise weist das Schlüsselwort async vor einer Funktionsdeklaration darauf hin, dass die Funktion asynchron ist.

Einige Schlüsselwörter sind reserviert, was bedeutet, dass sie nicht als Bezeichner für Variablendeklarationen, Funktionsdeklarationen usw. verwendet werden können. Sie werden oft als reservierte Wörter bezeichnet. Eine Liste dieser reservierten Wörter wird unten bereitgestellt. Nicht alle Schlüsselwörter sind reserviert – zum Beispiel kann async überall als Bezeichner verwendet werden. Einige Schlüsselwörter sind nur kontextuell reserviert – zum Beispiel ist await nur innerhalb des Körpers einer asynchronen Funktion reserviert, und let ist nur im strengen Modus-Code oder bei const- und let-Deklarationen reserviert.

Bezeichner werden immer nach Zeichenfolgenwert verglichen, sodass Escape-Sequenzen interpretiert werden. Zum Beispiel ist dies immer noch ein Syntaxfehler:

js
const els\u{65} = 1;
// `els\u{65}` encodes the same identifier as `else`

Reservierte Wörter

Diese Schlüsselwörter können nicht als Bezeichner für Variablen, Funktionen, Klassen usw. überall im JavaScript-Quellcode verwendet werden.

Die folgenden sind nur reserviert, wenn sie im strikten Modus gefunden werden:

  • let (auch reserviert in const, let und Klassendeklarationen)
  • static
  • yield (auch reserviert in Körpern von Generatorfunktionen)

Die folgenden sind nur reserviert, wenn sie in Modulcode oder in asynchronen Funktionskörpern gefunden werden:

Für die Zukunft reservierte Wörter

Die folgenden Wörter sind gemäß der ECMAScript-Spezifikation als zukünftige Schlüsselwörter reserviert. Sie haben derzeit keine besondere Funktionalität, könnten aber in Zukunft eine erhalten, weshalb sie nicht als Bezeichner verwendet werden können.

Diese sind immer reserviert:

  • enum

Die folgenden sind nur reserviert, wenn sie im strikten Modus gefunden werden:

  • implements
  • interface
  • package
  • private
  • protected
  • public

Für die Zukunft reservierte Wörter in älteren Standards

Die folgenden Wörter sind gemäß älterer ECMAScript-Spezifikationen (ECMAScript 1 bis 3) als zukünftige Schlüsselwörter reserviert.

  • abstract
  • boolean
  • byte
  • char
  • double
  • final
  • float
  • goto
  • int
  • long
  • native
  • short
  • synchronized
  • throws
  • transient
  • volatile

Bezeichner mit spezieller Bedeutung

Einige Bezeichner haben in bestimmten Kontexten besondere Bedeutungen, ohne dass sie reservierte Wörter sind. Dazu gehören:

Literale

Hinweis: Dieser Abschnitt behandelt Literale, die atomare Tokens sind. Objektliterale und Array-Literale sind Ausdrücke, die aus einer Reihe von Tokens bestehen.

Null-Literal

Siehe auch null für weitere Informationen.

js
null

Boolean-Literal

Siehe auch Boolean-Typ für weitere Informationen.

js
true
false

Numerische Literale

Die Number- und BigInt-Typen verwenden numerische Literale.

Dezimal

js
1234567890
42

Dezimal-Literale können mit einer Null (0) beginnen, gefolgt von einer weiteren Dezimalziffer, aber wenn alle Ziffern nach der führenden 0 kleiner als 8 sind, wird die Zahl als oktal interpretiert. Dies wird als veraltete Syntax angesehen, und Zahlenliterale mit 0 als Präfix, egal ob als oktal oder dezimal interpretiert, verursachen im strikten Modus einen Syntaxfehler – verwenden Sie daher stattdessen das 0o-Präfix.

js
0888 // 888 parsed as decimal
0777 // parsed as octal, 511 in decimal
Exponential

Das dezimale Exponential-Literal ist durch das folgende Format spezifiziert: beN; wobei b eine Basiszahl (Ganz- oder Fließzahl) ist, gefolgt von einem E- oder e-Zeichen (das als Trennzeichen oder Exponentialindikator dient) und N, das die Exponent- oder Potenzzahl – eine ganze Zahl – ist.

js
0e-5   // 0
0e+5   // 0
5e1    // 50
175e-2 // 1.75
1e3    // 1000
1e-3   // 0.001
1E3    // 1000

Binär

Die binäre Zahlensyntax verwendet eine führende Null, gefolgt von einem Klein- oder Großbuchstaben "B" (0b oder 0B). Jedes Zeichen nach dem 0b, das nicht 0 oder 1 ist, beendet die Lexemfolge.

js
0b10000000000000000000000000000000 // 2147483648
0b01111111100000000000000000000000 // 2139095040
0B00000000011111111111111111111111 // 8388607

Oktal

Die Oktalzahlensyntax verwendet eine führende Null, gefolgt von einem Klein- oder Großbuchstaben "O" (0o oder 0O). Jedes Zeichen nach dem 0o, das nicht im Bereich (01234567) liegt, beendet die Lexemfolge.

js
0O755 // 493
0o644 // 420

Hexadezimal

Die hexadezimale Zahlensyntax verwendet eine führende Null, gefolgt von einem Klein- oder Großbuchstaben "X" (0x oder 0X). Jedes Zeichen nach dem 0x, das nicht im Bereich (0123456789ABCDEF) liegt, beendet die Lexemfolge.

js
0xFFFFFFFFFFFFF // 4503599627370495
0xabcdef123456  // 188900967593046
0XA             // 10

BigInt-Literal

Der BigInt-Typ ist ein numerischer primitiver Datentyp in JavaScript, der Ganzzahlen mit beliebiger Präzision darstellen kann. BigInt-Literale werden erstellt, indem ein n an das Ende einer Ganzzahl angehängt wird.

js
123456789123456789n     // 123456789123456789
0o777777777777n         // 68719476735
0x123456789ABCDEFn      // 81985529216486895
0b11101001010101010101n // 955733

BigInt-Literale dürfen nicht mit 0 beginnen, um Verwechslungen mit veralteten Oktal-Literalen zu vermeiden.

js
0755n; // SyntaxError: invalid BigInt syntax

Für oktale BigInt-Zahlen verwenden Sie immer eine Null gefolgt von dem Buchstaben "o" (Groß- oder Kleinbuchstaben):

js
0o755n;

Für weitere Informationen über BigInt, siehe auch JavaScript-Datenstrukturen.

Numerische Trenner

Zur Verbesserung der Lesbarkeit von numerischen Literalen können Unterstriche (_, U+005F) als Trenner verwendet werden:

js
1_000_000_000_000
1_050.95
0b1010_0001_1000_0101
0o2_2_5_6
0xA0_B0_C0
1_000_000_000_000_000_000_000n

Beachten Sie diese Einschränkungen:

js
// More than one underscore in a row is not allowed
100__000; // SyntaxError

// Not allowed at the end of numeric literals
100_; // SyntaxError

// Can not be used after leading 0
0_1; // SyntaxError

String-Literale

Ein String-Literal ist null oder mehr Unicode-Codepunkte, eingeschlossen in Einzel- oder Doppelanführungszeichen. Unicode-Codepunkte können auch durch eine Escape-Sequenz dargestellt werden. Alle Codepunkte können wörtlich in einem String-Literal erscheinen, mit Ausnahme dieser Codepunkte:

  • U+005C \ (Backslash)
  • U+000D <CR>
  • U+000A <LF>
  • Dasselbe Anführungszeichen, das das String-Literal beginnt

Jeder Codepunkt kann in Form einer Escape-Sequenz erscheinen. String-Literale evaluieren zu ECMAScript-String-Werten. Beim Generieren dieser String-Werte werden die Unicode-Codepunkte als UTF-16 kodiert.

js
'foo'
"bar"

Die folgenden Unterabschnitte beschreiben verschiedene Escape-Sequenzen (\ gefolgt von einem oder mehreren Zeichen), die in String-Literalen verfügbar sind. Jede nicht unten aufgeführte Escape-Sequenz wird zu einer "Identitätsflucht", die zum Codepunkt selbst wird. Zum Beispiel ist \z dasselbe wie z. Es gibt eine veraltete Oktal-Escape-Sequenz-Syntax, die auf der Seite Deprecation und veraltete Funktionen beschrieben wird. Viele dieser Escape-Sequenzen sind auch in regulären Ausdrücken gültig – siehe Zeichencode-Escaping.

Escape-Sequenzen

Sonderzeichen können mittels Escape-Sequenzen codiert werden:

Escape-Sequenz Unicode-Codepunkt
\0 null character (U+0000 NULL)
\' einfaches Anführungszeichen (U+0027)
\" doppeltes Anführungszeichen (U+0022)
\\ Backslash (U+005C)
\n newline (U+000A LINE FEED; LF)
\r Wagenrücklauf (U+000D CARRIAGE RETURN)
\v vertikales Tab (U+000B LINE TABULATION)
\t Tabulator (U+0009 CHARACTER TABULATION)
\b Rückschritt (U+0008 BACKSPACE)
\f Formularvorschub (U+000C FORM FEED)
\ gefolgt von einem Zeilentrennzeichen leerer String

Die letzte Escape-Sequenz, \ gefolgt von einem Zeilentrennzeichen, ist nützlich, um ein String-Literal über mehrere Zeilen zu verteilen, ohne seine Bedeutung zu ändern.

js
const longString =
  "This is a very long string which needs \
to wrap across multiple lines because \
otherwise my code is unreadable.";

Achten Sie darauf, dass nach dem Backslash keine Leerzeichen oder andere Zeichen (außer einem Zeilenumbruch) stehen, sonst funktioniert es nicht. Wenn die nächste Zeile eingerückt ist, werden die zusätzlichen Leerzeichen auch im String-Wert vorhanden sein.

Sie können auch den + Operator verwenden, um mehrere Strings zu verketten, wie folgt:

js
const longString =
  "This is a very long string which needs " +
  "to wrap across multiple lines because " +
  "otherwise my code is unreadable.";

Beide der oben genannten Methoden führen zu identischen Strings.

Hexadezimale Escape-Sequenzen

Hexadezimale Escape-Sequenzen bestehen aus \x, gefolgt von genau zwei hexadezimalen Ziffern, die eine Code-Einheit oder einen Codepunkt im Bereich 0x0000 bis 0x00FF darstellen.

js
"\xA9"; // "©"

Unicode-Escape-Sequenzen

Eine Unicode-Escape-Sequenz besteht aus genau vier hexadezimalen Ziffern nach \u. Sie repräsentiert eine Code-Einheit in der UTF-16-Codierung. Für Codepunkte von U+0000 bis U+FFFF ist die Code-Einheit gleich dem Codepunkt. Codepunkte von U+10000 bis U+10FFFF erfordern zwei Escape-Sequenzen, die die beiden Code-Einheiten (ein Surrogatpaar) darstellen, die verwendet werden, um das Zeichen zu codieren; das Surrogatpaar ist vom Codepunkt verschieden.

Siehe auch String.fromCharCode() und String.prototype.charCodeAt().

js
"\u00A9"; // "©" (U+A9)

Unicode-Codepunkt-Escape

Eine Unicode-Codepunkt-Escape besteht aus \u{, gefolgt von einem Codepunkt in hexadezimaler Basis, gefolgt von }. Der Wert der hexadezimalen Ziffern muss im Bereich 0 bis 0x10FFFF inklusive liegen. Codepunkte im Bereich U+10000 bis U+10FFFF müssen nicht als Surrogatpaar dargestellt werden.

Siehe auch String.fromCodePoint() und String.prototype.codePointAt().

js
"\u{2F804}"; // CJK COMPATIBILITY IDEOGRAPH-2F804 (U+2F804)

// the same character represented as a surrogate pair
"\uD87E\uDC04";

Regulärausdrucks-Literale

Regulärausdrucks-Literale sind von zwei Schrägstrichen (/) eingeschlossen. Der Lexer konsumiert alle Zeichen bis zum nächsten unescapten Schrägstrich oder dem Ende der Zeile, es sei denn, der Schrägstrich erscheint innerhalb einer Zeichenklasse ([]). Einige Zeichen (nämlich die, die Bezeichnerteile sind) können nach dem Schließ-Schrägstrich erscheinen und Flags anzeigen.

Die lexikalische Grammatik ist sehr nachsichtig: Nicht alle regulären Ausdrucks-Literale, die als ein Token identifiziert werden, sind gültige reguläre Ausdrücke.

Siehe auch RegExp für weitere Informationen.

js
/ab+c/g;
/[/]/;

Ein regulärer Ausdruck kann nicht mit zwei Schrägstrichen (//) beginnen, da dies ein Zeilenkommentar wäre. Um einen leeren regulären Ausdruck anzugeben, verwenden Sie /(?:)/.

Vorlagenliterale

Ein Vorlagenliteral besteht aus mehreren Tokens: `xxx${ (Vorlagenkopf), }xxx${ (Vorlagenmitte) und }xxx` (Vorlagenende) sind einzelne Tokens, während zwischen ihnen jeder Ausdruck kommen kann.

Siehe auch Vorlagenliterale für weitere Informationen.

js
`string text`;

`string text line 1
 string text line 2`;

`string text ${expression} string text`;

tag`string text ${expression} string text`;

Automatisches Einfügen von Semikolons

Einige JavaScript-Anweisungen erfordern Semikolons (;) am Ende ihrer Syntaxdefinition. Dazu gehören:

Allerdings, um die Sprache zugänglicher und bequemer zu machen, ist JavaScript in der Lage, Semikolons automatisch einzufügen, wenn es den Tokenstrom konsumiert, so dass einige ungültige Tokenfolgen in gültige Syntax "korrigiert" werden können. Dieser Schritt erfolgt, nachdem der Programmtext gemäß der lexikalischen Grammatik in Tokens geparst worden ist. Es gibt drei Fälle, in denen Semikolons automatisch eingefügt werden:

1. Wenn ein Token, das von der Grammatik nicht erlaubt ist, auftritt und es von dem vorherigen Token durch mindestens ein Zeilentrennzeichen (einschließlich eines Blockkommentars, der mindestens ein Zeilentrennzeichen enthält) getrennt ist, oder das Token ein "}" ist, dann wird vor dem Token ein Semikolon eingefügt.

js
{ 1
2 } 3

// is transformed by ASI into:

{ 1
;2 ;} 3;

// Which is valid grammar encoding three statements,
// each consisting of a number literal

Das schließende ")" von do...while wird als ein Sonderfall durch diese Regel behandelt.

js
do {
  // …
} while (condition) /* ; */ // ASI here
const a = 1

Allerdings werden Semikolons nicht eingefügt, wenn das Semikolon dann zum Trenner im Kopf der for-Anweisung wird.

js
for (
  let a = 1 // No ASI here
  a < 10 // No ASI here
  a++
) {}

Semikolons werden auch nie als leere Anweisungen eingefügt. Zum Beispiel, im untenstehenden Code, wenn ein Semikolon nach ")" eingefügt wird, dann wäre der Code gültig, mit einer leeren Anweisung als if-Körper und der const-Deklaration als separate Anweisung. Da jedoch automatisch eingefügte Semikolons keine leeren Anweisungen werden können, verursacht dies, dass eine Deklaration zum Körper der if-Anweisung wird, was ungültig ist.

js
if (Math.random() > 0.5)
const x = 1 // SyntaxError: Unexpected token 'const'

2. Wenn das Ende des Token-Eingabestroms erreicht ist und der Parser nicht in der Lage ist, den einzigen Eingabestrom als komplettes Programm zu parsen, wird ein Semikolon am Ende eingefügt.

js
const a = 1 /* ; */ // ASI here

Diese Regel ist eine Ergänzung zur vorherigen Regel, speziell für den Fall, dass es kein "fehlerhaftes Token" gibt, sondern das Ende des Eingabestroms.

3. Wenn die Grammatik in einem bestimmten Bereich Zeilentrennzeichen verbietet, aber ein Zeilentrennzeichen gefunden wird, wird ein Semikolon eingefügt. Diese Bereiche umfassen:

  • expr <hier> ++, expr <hier> --
  • continue <hier> lbl
  • break <hier> lbl
  • return <hier> expr
  • throw <hier> expr
  • yield <hier> expr
  • yield <hier> * expr
  • (param) <hier> => {}
  • async <hier> function, async <hier> prop(), async <hier> function*, async <hier> *prop(), async <hier> (param) <hier> => {}
  • using <hier> id, await <hier> using <hier> id

Hier wird ++ nicht als Postfix-Operator angesehen, der auf die Variable b angewendet wird, da ein Zeilentrennzeichen zwischen b und ++ vorkommt.

js
a = b
++c

// is transformed by ASI into

a = b;
++c;

Hier gibt die return-Anweisung undefined zurück, und das a + b wird zu einer inhaltslosen Anweisung.

js
return
a + b

// is transformed by ASI into

return;
a + b;

Beachten Sie, dass ASI nur ausgelöst wird, wenn ein Zeilenumbruch Tokens, die sonst ungültige Syntax produzieren würden, trennt. Wenn das nächste Token als Teil einer gültigen Struktur geparst werden kann, werden keine Semikolons eingefügt. Zum Beispiel:

js
const a = 1
(1).toString()

const b = 1
[1, 2, 3].forEach(console.log)

Da () als Funktionsaufruf angesehen werden kann, wird ASI normalerweise nicht ausgelöst. Ebenso kann [] ein Zugriff auf ein Element sein. Der obenstehende Code ist äquivalent zu:

js
const a = 1(1).toString();

const b = 1[1, 2, 3].forEach(console.log);

Dies ist zufällig eine gültige Syntax. 1[1, 2, 3] ist ein Eigenschafts-Zugriff mit einem durch Komma verbundenen Ausdruck. Daher erhalten Sie Fehlermeldungen wie "1 ist keine Funktion" und "Eigenschaften von undefined (lesen von 'forEach') können nicht abgerufen werden", wenn Sie den Code ausführen.

Innerhalb von Klassen können Klassenfelder und Generator-Methoden auch ein Fallstrick sein.

js
class A {
  a = 1
  *gen() {}
}

Es wird als folgendes angesehen:

js
class A {
  a = 1 * gen() {}
}

Und es wird deshalb einen Syntaxfehler bei { geben.

Es gibt einige Faustregeln für den Umgang mit ASI, wenn Sie einen stil ohne Semikolons erzwingen möchten:

  • Schreiben Sie Postfix-++ und -- auf derselben Zeile wie ihre Operanden.

    js
    const a = b
    ++
    console.log(a) // ReferenceError: Invalid left-hand side expression in prefix operation
    
    js
    const a = b++
    console.log(a)
    
  • Die Ausdrücke nach return, throw oder yield sollten auf derselben Zeile wie das Schlüsselwort stehen.

    js
    function foo() {
      return
        1 + 1 // Returns undefined; 1 + 1 is ignored
    }
    
    js
    function foo() {
      return 1 + 1
    }
    
    function foo() {
      return (
        1 + 1
      )
    }
    
  • In ähnlicher Weise sollte der Bezeichner nach break oder continue auf derselben Zeile wie das Schlüsselwort stehen.

    js
    outerBlock: {
      innerBlock: {
        break
          outerBlock // SyntaxError: Illegal break statement
      }
    }
    
    js
    outerBlock: {
      innerBlock: {
        break outerBlock
      }
    }
    
  • Das => einer Pfeilfunktion sollte auf derselben Zeile wie das Ende seiner Parameter sein.

    js
    const foo = (a, b)
      => a + b
    
    js
    const foo = (a, b) =>
      a + b
    
  • Das async von asynchronen Funktionen, Methoden usw. kann nicht direkt von einem Zeilentrennzeichen gefolgt werden.

    js
    async
    function foo() {}
    
    js
    async function
    foo() {}
    
  • Das Schlüsselwort using in using- und await using-Anweisungen sollte auf derselben Zeile wie der erste deklarierte Bezeichner stehen.

    js
    using
    resource = acquireResource()
    
    js
    using resource
      = acquireResource()
    
  • Wenn eine Zeile mit einem der Zeichen (, [, `, +, -, / (wie in regulären Ausdrücken) beginnt, setzen Sie ein Semikolon davor oder enden Sie die vorherige Zeile mit einem Semikolon.

    js
    // The () may be merged with the previous line as a function call
    (() => {
      // …
    })()
    
    // The [ may be merged with the previous line as a property access
    [1, 2, 3].forEach(console.log)
    
    // The ` may be merged with the previous line as a tagged template literal
    `string text ${data}`.match(pattern).forEach(console.log)
    
    // The + may be merged with the previous line as a binary + expression
    +a.toString()
    
    // The - may be merged with the previous line as a binary - expression
    -a.toString()
    
    // The / may be merged with the previous line as a division expression
    /pattern/.exec(str).forEach(console.log)
    
    js
    ;(() => {
      // …
    })()
    ;[1, 2, 3].forEach(console.log)
    ;`string text ${data}`.match(pattern).forEach(console.log)
    ;+a.toString()
    ;-a.toString()
    ;/pattern/.exec(str).forEach(console.log)
    
  • Klassenfelder sollten vorzugsweise immer mit Semikolon enden – zusätzlich zur vorherigen Regel (einschließlich einer Felddeklaration, gefolgt von einer berechneten Eigenschaft, da letztere mit [ beginnt), sind Semikolons auch zwischen einer Felddeklaration und einer Generator-Methode erforderlich.

    js
    class A {
      a = 1
      [b] = 2
      *gen() {} // Seen as a = 1[b] = 2 * gen() {}
    }
    
    js
    class A {
      a = 1;
      [b] = 2;
      *gen() {}
    }
    

Spezifikationen

Spezifikation
ECMAScript® 2027 Language Specification

Browser-Kompatibilität

Siehe auch