JavaScript – Das Handbuch für die Praxis. David Flanagan
eine globale Variable deklariert, indem dem globalen Objekt eine neue Eigenschaft hinzugefügt wird.)
Bei Funktionen, die als Funktionen (und nicht als Methoden) aufgerufen wurden, hat this im strict-Modus den Wert undefined. (Im nicht-strikten Modus wird Funktionen, die als Funktionen aufgerufen werden, immer das globale Objekt als this-Wert übergeben.) Wird zudem im strict-Modus eine Funktion mit call() oder apply() (siehe 8.7.4) aufgerufen, wird als this-Wert das erste Argument von call() oder apply() verwendet. (Im nicht-strikten Modus werden null und undefined durch das globale Objekt ersetzt und Werte, die keine Objekte sind, in Objekte umgewandelt.)
Im strict-Modus wird bei Zuweisungen an nicht schreibbare Eigenschaften und bei Versuchen, neue Eigenschaften auf nicht erweiterbaren Objekten zu erstellen, ein TypeError ausgelöst. (Im nicht-strikten Modus scheitert beides ohne Fehlermeldung.)
Im strict-Modus kann Code, der an eval() übergeben wird, keine Variablen oder Funktionen im Geltungsbereich (Scope) des Aufrufers deklarieren bzw. definieren. Stattdessen existieren Variablen- und Funktionsdefinitionen in einem neuen Geltungsbereich, der speziell für eval() erstellt wird. Dieser Geltungsbereich wird verworfen, wenn eval() zum Aufrufer zurückkehrt.
Im strict-Modus enthält das Arguments-Objekt (siehe 8.3.3) einer Funktion eine statische Kopie der Werte, die der Funktion übergeben werden. Im nichtstrikten Modus verhält sich das Arguments-Objekt eher »magisch«: Die Array-Elemente und benannte Funktionsparameter verweisen beide auf den gleichen Wert.
Im strict-Modus wird ein SyntaxError ausgelöst, wenn auf den delete-Operator ein nicht qualifizierter Identifier wie eine Variable, eine Funktion oder ein Funktionsparameter folgt. (Im nicht-strikten Modus bleibt ein solcher delete-Ausdruck einfach wirkungslos und wird zu false ausgewertet.)
Im strict-Modus löst der Versuch, eine nicht konfigurierbare Eigenschaft zu löschen, einen TypeError aus. (Im nicht-strikten Modus schlägt der Versuch fehl, und der delete-Ausdruck wird zu false ausgewertet.)
Im strict-Modus ist es ein Syntaxfehler, wenn ein Objektliteral mehrere Eigenschaften mit dem gleichen Namen definiert. (Im nicht-strikten Modus tritt kein Fehler auf.)
Im strict-Modus ist es ein Syntaxfehler, wenn eine Funktionsdeklaration mehrere Parameter mit dem gleichen Namen hat. (Im nicht-strikten Modus tritt kein Fehler auf.)
Im strict-Modus sind keine oktalen Ganzzahlliterale erlaubt (also Literale, die mit einer 0 beginnen, auf die kein b, o oder x folgt). (Im nicht-strikten Modus erlauben einige Implementierungen Oktalliterale.)
Im strict-Modus werden die Identifier eval und arguments wie Schlüsselwörter behandelt. Ihr Wert darf nicht verändert werden. Sie können diesen Identifiern weder einen Wert zuweisen oder sie als Variable deklarieren noch sie als Namen für Funktionen, Funktionsparameter oder den Parameter eines catch-Blocks verwenden.
Im strict-Modus gibt es nur eingeschränkte Möglichkeiten, den Aufrufstapel zu untersuchen. arguments.caller und arguments.callee lösen in einer Funktion im strict-Modus beide einen TypeError aus. Funktionen im strict-Modus besitzen außerdem caller- und arguments-Eigenschaften, bei denen Leseversuche zu einem TypeError führen. (Einige Implementierungen definieren diese nicht dem Standard entsprechenden Eigenschaften auf nicht-strikten Funktionen.)
5.7Deklarationen
Die Schlüsselwörter const, let, var, function, class, import und export sind formal betrachtet keine Anweisungen, sehen ihnen aber sehr ähnlich. Da wir sie in diesem Buch informell als Anweisungen bezeichnen, haben sie eine Erwähnung in diesem Kapitel verdient.
Diese Schlüsselwörter sind eher Deklarationen als Anweisungen. Zu Beginn dieses Kapitels haben wir gesagt, dass Anweisungen »etwas bewirken«. Deklarationen dienen dazu, neue Werte zu definieren und ihnen Namen zu geben, mit denen wir uns auf diese Werte beziehen können. Von sich aus tun sie nicht viel, aber indem sie Werten Namen verleihen, bestimmen sie in einem wichtigen Sinn die Bedeutung der anderen Anweisungen in Ihrem Programm.
Wird ein Programm ausgeführt (»läuft es«), werden die vorhandenen Ausdrücke ausgewertet und die enthaltenen Anweisungen ausgeführt. Deklarationen »laufen« nicht auf die gleiche Weise, sondern definieren die Struktur des Programms selbst. Grob betrachtet, kann man sich Deklarationen als die Teile des Programms vorstellen, die verarbeitet werden, bevor der Code ausgeführt wird.
JavaScript-Deklarationen werden zur Definition von Konstanten, Variablen, Funktionen und Klassen sowie zum Importieren und Exportieren von Werten zwischen Modulen verwendet. Die nächsten Unterabschnitte zeigen Beispiele für diese verschiedenen Deklarationen. Sie alle werden an anderer Stelle in diesem Buch ausführlicher behandelt.
5.7.1const, let und var
Die const-, let- und var-Deklarationen werden in 3.10 behandelt. In ES6 und später deklariert const Konstanten und let Variablen. Vor ES6 konnte man Variablen nur mit dem Schlüsselwort var deklarieren, und es gab noch keine Möglichkeit, Konstanten zu deklarieren. Der Geltungsbereich von Variablen, die mit var deklariert werden, ist funktions- und nicht blockbezogen. Das ist eine mögliche Fehlerquelle, und in modernem JavaScript gibt es wirklich keinen Grund, var anstelle von let einzusetzen.
const TAU = 2*Math.PI;
let radius = 3;
var circumference = TAU * radius;
5.7.2function
Die function-Deklaration wird verwendet, um Funktionen zu definieren. Funktionen werden detailliert in Kapitel 8 behandelt. (Der Begriff function ist uns auch in 4.3 begegnet, wo er als Teil eines Funktionsausdrucks und nicht als Funktionsdeklaration verwendet wurde.) Eine Funktionsdeklaration sieht wie folgt aus:
function area(radius) {
return Math.PI * radius * radius;
}
Eine Funktionsdeklaration erzeugt ein Funktionsobjekt und weist es dem angegebenen Namen zu – in diesem Beispiel area. An anderer Stelle in unserem Programm können wir auf die Funktion zugreifen und ihren Code ausführen, indem wir diesen Namen verwenden. Die Funktionsdeklarationen in einem beliebigen Block von JavaScript-Code werden verarbeitet, bevor dieser Code ausgeführt wird, und die Funktionsnamen sind im gesamten Block an die Funktionsobjekte gebunden. Wir sprechen davon, dass Funktionsdeklarationen das Hoisting (»anheben«) nutzen, weil es so wirkt, als seien sie auf die oberste Ebene des Geltungsbereichs gerückt worden, in dem sie definiert sind. Im Ergebnis kann Code, der eine Funktion aufruft, in einem Programm vor dem Code existieren, mit dem die Funktion deklariert wird.
12.3 beschreibt eine besondere Art von Funktion, die als Generator bekannt ist. Generatordeklarationen benutzen das Schlüsselwort function, gefolgt von einem Sternchen. 13.3 beschreibt asynchrone Funktionen, die ebenfalls mit dem Schlüsselwort function deklariert werden, denen aber noch das Schlüsselwort async vorangestellt wird.
5.7.3class
In ES6 und später erzeugt eine class-Deklaration eine neue Klasse und gibt ihr einen Namen, mit dem wir auf sie verweisen können. Klassen werden ausführlich in Kapitel 9 beschrieben. Eine einfache Klassendeklaration könnte wie folgt aussehen:
class