Konstanten in JavaScript
Durch »const« kann eine neue Variable angelegt werden.
Bisher haben wir neue Einträge durch Zuweisungen angelegt. Dies gilt aber als fehlerträchtig, weswegen es ja auch von »"use strict";« schon teilweise verboten wird. Das Voranstellen von »this.« ist aber auch nicht unbedingt weniger fehlerträchtig.
Tatsächlich wird empfohlen, neue Einträge nicht durch eine Zuweisung sondern durch eine Deklaration anzulegen.
Das Anlegen einer Variablen mit »const« nennt man auch Deklaration der Variablen.
Durch Verwendung einer Deklaration drückt man aus, daß man etwas neu anlegen will.
Vorteile von »const«
- Durch »const« wird dem Leser eines Programmes die Absicht, daß eine neue Variable angelegt werden soll, klar signalisiert. Eine einfache Zuweisung an einen Eintragsausdruck könnte hingegen auch bedeuten, daß ein schon vorhandener Eintrag nur geändert werden soll.
- Durch »const« werden Variablen in einem speziellen Bereich (declarative Environment Record ) angelegt, der unabhängig von den Eigenschaften des globalen Objekts ist. Dadurch wird es ausgeschlossen, daß durch das Deklarieren einer Variablen mit »const« ein schon vorhandenere Eintrag im globalen Objekt mit demselben Namen unbeabsichtigt verändert wird. Alle Einträge im globalen Objekt bleiben unverändert erhalten.
- Falls versehentlich ein schon einmal deklarierter Name erneut mit »const« deklariert wird, so wird dies als Fehler erkannt und gemeldet.
- Wir haben bisher Eigenschaften des globalen Objektes »this« auch manchmal als „Variablen“ bezeichnet. Offiziell sind diese Eigenschaften aber gar keine Variablen. Erst »const« erlaubt es uns, „richtige Variablen“ anzulegen.
- Da »const« eine spätere Veränderung des Wertes einer Variablen verbietet, können Variablen nicht versehentlich verändert werden. Hier könnte man natürlich einwenden, daß man Variablen oft tatsächlich verändern will. Jedoch kommt es in der Praxis tatsächlich erstaunlich oft vor, daß Variablen gar nicht mehr verändert werden müssen! Wie Variablen bei Bedarf doch verändert werden können wird etwas später in diesem Kurs gezeigt werden.
Deklarationen
Um eine Deklaration einer Konstanten zu schreiben, schreibt man das Schlüsselwort »const« vor eine Zuweisung an jene Konstante.
Durch »const x = 1;« wird eine neue Konstante mit dem Namen »x« und dem Wert »1« angelegt.
- Deklaration einer Konstanten »x« mit dem Wert »1«
const x = 1;
undefined
Unter der Initialisierung einer Konstanten verstehen wir die Festlegung des Wertes der Konstanten innerhalb ihrer Deklaration. Der Initialisierungsausdruck ist der Ausdruck rechts vom Gleichheitszeichen.
Eine solche Deklaration hat als Wert immer »undefined«. Die Wirkung besteht im Anlegen der neuen Konstanten mit dem angegebenen Wert (wie bei einer Zuweisung).
»const x = 1;« ist auch im strengen Modus erlaubt, während »x = 1;« im strengen Modus nicht erlaubt ist, wenn es noch keine Eigenschaft »this.x« gibt.
Bei einer Verwendung hat die Konstante dann den festgelegten Wert.
- Verwendung einer Konstanten »x«
x
1
Deklarationen sind einmalig
Eine Konstante kann nicht mit dem Namen einer schon zuvor angelegten Konstanten erneut angelegt werden.
- Deklaration einer Konstanten »x« mit dem Wert »1«
const x = 1;
undefined
- Versuch der erneuten Deklaration einer Konstanten »x« mit dem Wert »1«
const x = 1;
SyntaxError: redeclaration of const x
Konstanten sind keine Einträge
Konstanten sind keine Einträge im globalen Objekt. Sie werden vielmehr in einem anderen, unabhängigen Verzeichnis eingetragen.
- Deklaration einer Konstanten »x« mit dem Wert »1«
const x = 1;
undefined
- Auswertung
this.x
undefined
Konstanten existiert in einer „lexikalischen Umgebung“ und nicht im globalen Objekt. Daher kann eine globale Konstante, wie »x«, nicht mit »this.x« erreicht werden, sondern nur mit »x« alleine.
(Die Fachbezeichnung für die „lexikalische Umgebung“ lautet “declarative environment record ”.)
Wir haben die Namen neuer globaler Einträge oft auf Namen mit weniger als vier Zeichen eingeschränkt, weil hier Kollisionen mit schon definierten Namen weniger wahrscheinlich sind. Bei Konstanten ist keine solche Einschränkung nötig.
»Object.getOwnPropertyDescriptor«
Wir hatten schon einmal gesehen, daß die Funktion »Object.getOwnPropertyDescriptor« es erlaubt, Informationen über einen Eintrag in einem Verzeichnis zu erhalten. Da Konstanten keine Einträge sind, kann »Object.getOwnPropertyDescriptor« nicht auf sie angewendet werden. Die lexikalische Umgebung, in der Konstanten gespeichert werden, ist kein Verzeichnis, auf das man direkt zugreifen kann..
Konstanten verdecken globale Einträge
Wenn es sowohl eine Konstante als auch einen globalen Eintrag mit dem gleichen Namen gibt, dann steht jener Name für die Konstante.
- Deklaration einer Konstanten »x« mit dem Wert »1«
const x = 1;
undefined
- Zuweisung an eine globale Eigenschaft
this.x = 2
undefined
- Auswertung eines Bezeichners
x
1
Um den globalen Eintrag zu erreichen kann eine Qualifikation mit »this« verwendet werden.
- Auswertung eines Eintragsausdrucks
this.x
2
Konstanten sind konstant
Konstanten sind konstant. Das heißt, daß der Wert einer Konstante nach ihrer Definition nicht mehr verändert werden kann.
- Deklaration einer Konstanten »x« mit dem Wert »1«
const x = 1;
undefined
- Versuch einer Veränderung des Wertes der Konstanten
x = 2;
TypeError: invalid assignment to const `x'
Falls der Wert einer Konstanten aber ein Verzeichnis ist, so kann dieses Verzeichnis durchaus verändert werden.
- Deklaration einer Konstanten »d« als Verzeichnis
const d = ()=>0;
undefined
- Änderung des Verzeichnisses
d.a = 2;
2
- Auswertung
d.a
2
- Änderung des Verzeichnisses
d.a = 8;
8
- Auswertung
d.a
8
Was bei einer Konstanten »d« nicht erlaubt ist, ist eine Zuweisung, bei welcher »d« alleine auf der linken Seite steht.
- Versuch einer Veränderung des Wertes der Konstanten
d = 2;
TypeError: invalid assignment to const `d'
Kompakte Definition mehrerer Konstanten
Es ist möglich, mehrere Konstanten mit einer einzigen Konstantendefinition zu definieren, indem mehrere Zuweisungen hinter »const« durch ein Komma getrennt werden.
- Deklaration mehrerer Konstanten
const a = 1, b = 2, c = 3;
undefined
- Auswertung
a + b + c
6
Wirkungen von Deklarationen
Eine Deklaration kann (wie eine Zuweisung) eine Wirkung haben, wenn die Auswertung des Initialisierungsausdrucks (des Ausdrucks rechts vom Gleichheitszeichen) eine Wirkung hat.
Im folgenden Beispiel erhält »x« den Wert »undefined«, und die Wirkung der Auswertung der Deklaration »console.log( "f" )« ist die Ausgabe der Zeile »f«.
- Ein Skript
const x = console.log( "f" );
- Ausgabe
f
Das Puffern von Werten
Ein Wert, dessen Berechnung aufwendig ist, kann in einer Konstanten gespeichert werden, um eine mehrfache aufwendige Berechnung zu vermeiden. Im folgenden Beispiel wird die erste Version eines Skripts durch eine zweite Version ersetzt, in welcher der Sinus von »2.2« nur noch einmal berechnet wird.
- Ein Skript (erste Version)
console.log( Math.sin( 2.2 ));
console.log( Math.sin( 2.2 ));- Ein Skript (zweite Version)
const s22 = Math.sin( 2.2 );
console.log( s22 );
console.log( s22 );
Allerdings kann diese Technik nur bei Berechnungen angewendet werden, die immer denselben Wert ergeben. Die beiden folgenden Skripte haben beispielsweise in der Regel ein unterschiedliches Verhalten, da das erste Skript zwei verschiedenen Zufallszahlen ausgeben könnte, während das zweite Skripte dieselbe Zufallszahl zwiefach ausgibt.
- Ein Skript (erste Version)
console.log( Math.random() );
console.log( Math.random() );- Ein Skript (zweite Version)
const r = Math.random();
console.log( r );
console.log( r );
Konstantendeklaration und »eval«
Eine Konstantendeklaration produziert keinen Wert. Daher ist der Wert von »eval( "2; const a = 3;" )« weiterhin der zuletzt produzierte Wert »2«.
Konstantennamen dürfen lang sein
Wir hatten für globale Einträge kurze Namen mit bis zu drei Zeichen bevorzugt, da hier eine Kollision mit schon vordefinierten Einträgen als unwahrscheinlicher erschien. Bei Namen von Konstanten sind solche Kollisionen kaum zu befürchten, deswegen können für diese auch längere Namen verwendet werden.
Konstantendeklarationen und »"use strict"« ⃗
Im strengen Modus können bestimmte reservierte Bezeichner nicht deklariert werden.
- Skript
"use strict"; const private = 2;
SyntaxError: private is a reserved identifier
- Skript
"use strict"; const eval = 9;
SyntaxError: redefining eval is deprecated
Aus der freien Wildbahn Minifikation
Bei der Minifikation eines JavaScript -Programmes werden längere Namen durch möglichst kurze Namen (oft mit einem Buchstaben) ersetzt, um ein möglichst kurzes Programm zu erhalten.
Der Programmierer behält dabei aber seine wartungsfreundliche Version mit langen Variablennamen.
Ein Programm mit kurzen Namen kann schneller übertragen und vielleicht auch etwas schneller ausgeführt werden. Wenn es veröffentlicht wird, dann erschwert es Dritten, die den Quelltext lesen können, auch das Verständnis und die Analyse des Quelltextes, was manchmal ebenfalls so gewünscht wird. Eine solche Veränderung eines Quelltextes, deren Ziel es ist, sein Verständnis zu erschweren, nennt man auch eine Obfuskation des Quelltextes. Die Minifikation ist nur eine von mehreren Techniken der Obfuskation .
Die Minifikation wird oft automatisch vorgenommen. Es gibt aber auch eine manuelle Variante, bei welcher kurze Namen für Ausdrücke definiert werden, die später öfter verwendet werden, um den Quelltext kleinzuhalten.
- Beispiel für manuelle Minifikation
const an = navigator.appName;
- Beispiel für manuelle Minifikation
const t = this;
Umhüllen einer neuen Funktion *
Eine Funktion kann auch eine Funktion als Argument oder als Ergebnis haben.
Die Funktion »umhuelle_mit_ausgabe« akzeptiert eine Funktion »umhuellte_funktion« und ergibt eine neue Funktion (Zeile 2 bis 6). Die neue Funktion akzeptiert ein Argument für ihren Parameter »x« und liefert dasselbe Ergebnis »result« wie die umhüllte Funkton, aber zeigt zusätzlich noch den Beginn und das Ende ihrer Aktivität durch jeweils eine Ausgabe an.
- Auswertung
umhuelle_mit_ausgabe = umhuellte_funktion =>
x =>
{ console.log( "( " + umhuellte_funktion.name + " " + x );
const result = umhuellte_funktion( x );
console.log( " " + umhuellte_funktion.name + " " + x + " )" );
return result; };
Wir können nun aus dieser Funktion
- Definition
cos = umhuelle_mit_ausgabe( Math.cos );
- Definition
sin = umhuelle_mit_ausgabe( Math.sin );
- Auswertung
cos( 0 )
( cos 0
cos 0 )
1
- Auswertung
sin( cos( 0 ))
( cos 0
cos 0 )
( sin 1
sin 1 )
0.8414709848078965
Übungsfragen
? Ausgabe vorhersagen
Welche Ausgabe erzeugt das folgende Skript?
(Bei solche Übungsfragen, soll man sich das Programm selber durchlesen und die Ausgabe dann richtig vorhersagen. Man soll das Skript also nicht mit einer JavaScript -Implementation starten.
- Skript
const a = 5;
console.log( a + 1 );
console.log( a );
? Konstanten
Welche Vor- und Nachteile hat die Verwendung von Texten und lokalen Konstanten in dem Skript zur Temperaturumrechnung gegenüber einem Programm, welches das gleiche Ergebnis ausgibt, aber an Stelle der Texte und Konstanten nur Numeralia und Operatoren verwendet?
Welches Skript gefällt Ihnen besser?
Skript
const temperatur = 2;
const celsiusversatz = 273.15;
const celsiustemperatur = temperatur - celsiusversatz;
const ausgabe = "Temperatur von " + temperatur + " Kelvin = "
+ celsiustemperatur + " Grad Celsius";
console.log( ausgabe );Ausgabe
Temperatur von 2 Kelvin = -271.15 Grad Celsius
Skript
console.log( 2 - 273.15 );
Konsole
-271.15
Übungsaufgaben
/ Deklaration einer Konstanten
Schreiben Sie ein Skript, in welchem eine Konstante mit dem Namen »i« und dem Wert »2« deklariert wird. Das Skript soll dann den Wert jener Konstanten ausgeben.