ES6: Variablen deklarieren
Ziele
- Du weisst, wie du Variablen deklarierst.
- Du weisst, wann du eine Variable mit
var,letoderconstdeklarieren musst. - Du kannst das “Object Destructuring Assignment” anwenden.
Basics
In JavaScript deklarierst du Variablen mit dem let- oder const-Keyword - egal welcher Typ die Variable haben wird.
Die folgenden Beispiele zeigen auf, wie du Variablen deklarieren und zuweisen/assignen kannst:
| |
Wie du siehst, kannst du eine mit let deklarierte Variable verändern. Versuchst du, eine const-Variable neu zu deklarieren, wird ein Fehler geworfen. Es ist jedoch durchaus möglich, einzelne Attribute einer const-Variable zu ändern.
Als Grundsatz gilt: Verwende immer
const, ausser du willst später der Variable im gleichen Scope (nächster Abschnitt) einen anderen Wert zuweisen. Dann verwendelet.
Die Verwendung von const per Default hat den Vorteil, dass so Side-Effects vermieden werden können, welche aufgrund der Neuzuweisung von Variablen auftreten können.
Wenn du beispielsweise viele Variablen in einer Funktion hast, müsstest du zuerst sicherstellen, dass deine neue Variable keine bestehende Variable im gleichen Scope überschreibt. Verwendest du standardmässig const, wird im Falle einer Doppelzuweisung ein Fehler geworfen, der dir dann direkt ins Auge sticht.
JavaScript besitzt keine Typisierung
JavaScript ist eine dynamisch typisierte Sprache, was bedeutet, dass die Typen der Variablen und Ausdrücke erst zur Laufzeit und nicht zur Kompilierungszeit festgelegt werden. Im Gegensatz dazu haben andere Sprachen wie Java oder C++ eine statische Typisierung, bei der der Typ einer Variable oder eines Ausdrucks bereits zur Kompilierungszeit festgelegt wird.
In JavaScript können Variablen während der Laufzeit ohne Einschränkung ihren Typ ändern. Beispielsweise kann eine Variable zunächst als String initialisiert werden und später im Code auf einen numerischen Wert aktualisiert werden. Das liegt daran, dass JavaScript die Datentypen von Variablen dynamisch zuweist und ihnen erlaubt, sich während der Laufzeit zu ändern.
Obwohl diese Flexibilität ein Vorteil von JavaScript ist, kann sie auch zu unerwarteten Verhaltensweisen führen, wenn der/die Entwickler:in nicht aufpasst. In der Tat kann die mangelnde Typsicherheit in JavaScript ein Nachteil sein, da sie dazu führen kann, dass sich Fehler erst zur Laufzeit manifestieren, anstatt dass sie bereits beim Kompilieren erkannt werden.
An diesem Beispiel lässt sich gut erkennen, dass sich die Typen von Variablen während der Laufzeit verändern lassen:
| |
Allerdings gibt es in modernen Versionen von JavaScript (ab ES6) die Möglichkeit, (optionale) Typisierung durch das Verwenden von Typ-Annotationen oder TypeScript hinzuzufügen, welche einer statische Typisierung ähneln können. Dies kann helfen, die Lesbarkeit und die Sicherheit deines Codes zu erhöhen. Wie du die Typen der Parameter in einer Funktion bestimmen kannst, wirst du im Kapitel JSDoc genauer sehen.
ES6
ES6, auch bezeichnet als ECMAScript 2015 oder ECMAScript 6, war die zweite grössere Revision von JavaScript als Sprache, man kann es auch als Update für JavaScript selbst betrachten. Im Rahmen der Einführung von ES6 wurden viele neue Funktionalitäten zur Sprache hinzugefügt, unter anderem:
- Der
let-Schlüsselbegriff - Der
const-Schlüsselbegriff - Arrow Functions
- Die
for/of-Schlaufe - Map Objects
- Set Objects
- Klassen
- Promises
- Verschiedene String-Operationen wie beispielsweise
String.includes(),String.startsWith()etc. - Verschiedene Array-Operationen wie beispielsweise
Array.find(),Array.keys()etc. - JavaScript-Module
- Und weitere.
Eine vollständige Liste aller Neuerungen im Rahmen der Einführung von ES6 findest du auf der folgenden Webseite: Neuerungen in ES6
Scope
Block-Scope
Variablen, die mit const oder let definiert wurden, sind in ihrem jeweiligen Scope sichtbar und verwendbar.
Es ist wichtig, dass du den folgenden Code komplett verstehst und weisst, wieso er zum entsprechenden Resultat führt - und warum die Verwendung von const nicht zu einem Fehler führt:
| |
Dies produziert folgenden Output:
| |
Global Scope und Function Scope
Vor ES6 kannte JavaScript keinen Block-Scope, sondern nur einen globalen Scope und einen Function Scope.
Um das zu verstehen, lass diesen Code einmal laufen:
| |
Du solltest dann folgende Zahlen im Output erhalten:
| |
Wie du siehst, haben alle Variablen, die innerhalb einer Funktion mit var deklariert werden, den gleichen Scope:
Das bedeutet, wenn du beispielsweise eine var-Variable, die du ganz oben in der Funktion definierst, veränderst, wenn du eine gleichnamige später in einer for-Schleife mit var definierst.
Einen solchen Function Scope haben nur Variablen, die mit var definiert wurden. Variablen, die mit let oder const definiert wurden, haben einen Block-Scope und sind daher innerhalb ihres Blocks (for/while-Schlaufe, if/else-Block, Funktion, Datei) definiert und sichtbar.
In Java gilt der Block Scope immer.
Hierzu findest du eine Aufgabe im Lab (Aufgabe 4).
Wann var verwenden?
Folgender Grundsatz gilt:
Verwende nie
var, ausser du musst sicherstellen, dass der Code in Browsern funktioniert, welche zuletzt vor 2015 aktualisiert wurden.
Wenn du wissen willst, wieso var nicht mehr verwendet werden sollte, dann kannst du dein Wissen auf dieser Seite vertiefen: https://medium.com/@codingsam/awesome-javascript-no-more-var-working-title-999428999994.
typeof Operator
typeof ist ein Operator, der den Datentyp eines Ausdrucks oder einer Variable zurückgibt. Er kann verwendet werden, um zu überprüfen, ob eine Variable einen primitiven Datentypen (auch string) hat, bevor eine Operation durchgeführt wird, die nur für diesen Datentyp geeignet ist.
typeof gibt einen String zurück, der den Datentyp des Operanden darstellt. Die möglichen Rückgabewerte sind:
undefinedfür undefined-Wertebooleanfür boolesche Wertenumberfür Zahlenstringfür Zeichenkettenobjectfür Objekte (einschliesslich Arrays und null-Werte)functionfür Funktionen
| |
Es ist wichtig zu beachten, dass typeof nicht immer genau den Datentyp zurückgibt, den man erwartet. Insbesondere gibt typeof(null) “object” aus, obwohl null eigentlich kein Objekt ist. Es ist daher oft besser, zusätzlich zu typeof andere Überprüfungen durchzuführen, um sicherzustellen, dass eine Variable den erwarteten Datentyp hat.
instanceof Operator
Auch der instanceof Operator wird verwendet, um festzustellen, ob ein Objekt einen bestimmten Typ hat. Er gibt ein boolesches Ergebnis zurück, das angibt, ob das übergebene Objekt eine Instanz des angegebenen Typs ist.
Zu beachten ist zudem, dass instanceof bei primitive Datentypen nicht zur Überprüfung geeignet ist, da diese keine Objekte sind. In diesem Fall würde sich typeof besser eignen.
| |
Man kann auch instanceof und typeof kombinieren, um sicherstellen, dass die Variable sowohl den erwarteten Datentyp als auch den erwarteten Wertebereich entspricht.
| |
typeof vs. instanceof
typeof ist besser geeignet, um primitive Datentypen wie Strings, numbers und Booleans zu überprüfen.
instanceof ist hingegen besser geeignet, um den Datentyp von Objekten zu überprüfen, einschliesslich Arrays, Funktionen und benutzerdefinierten Objekten. Damit lässt sich ebenfalls prüfen, ob ein Objekt auf Basis einer bestimmten Klasse erstellt wurde.
Destructuring Assignment
In JavaScript lässt sich oft beobachten, dass mehrere Variablen auf einmal definiert werden.
Wie in anderen Programmiersprachen kannst du mehrere Variablen in einem einzigen Statement definieren (das ist kein Destructuring Assignment!):
| |
So kommt es oft vor, dass du mit einem einzigen Methodenaufruf mehrere Werte zurückbekommst - zum Beispiel in Form eines Arrays/ einer Liste oder in Form eines Objekts. Oft willst du dann die einzelnen Werte in eigenen Variablen speichern. Wie du das machen kannst, wird in den nächsten zwei Abschnitten behandelt:
Destructuring Arrays
Hast du ein Array und willst zum Beispiel den ersten und zweiten Wert aus diesem je einer Variablen zuweisen, dann wäre die normale Vorgehensweise die folgende:
| |
Diese Schreibweise lässt sich aber mit folgender Syntax vereinfachen:
| |
Ist beispielsweise das erste Element ein Index/Key/Zeilen- beziehungsweise Spaltenname und der Rest das eigentliche Array, dann hilft dir vielleicht diese Schreibweise (achte hierbei auf die Nutzung des Spread-Operators (...):
| |
Hier hat name den Wert “ColumnName” und values ist das Array [1, 2, 3, 4].
Object Destructuring
Diese Schreibweise hast du sicher bereits einmal gesehen:
| |
Das ist grundsätzich ein relativ einfaches Prinzip. Wenn du den nachfolgenden Code verstanden hast, dann weisst du alles, was du zu diesem Thema wissen musst:
| |
In diesem Beispiel haben wir den Wert für a in die Variable one kopiert.
Wie du siehst, spielt hier die Reihenfolge der Variablen keine Rolle.
Die ersten zwei Anweisungen könnten auch in einer zusammengefasst werden:
| |
Ignorieren wir zuerst die Variable a bzw. one.
- Auf der linken Seite deklarieren wir die Variablen
dundb. - Die Felder
dundbaus dem Objekt auf der rechten Seite werden in die Variablendundbauf der linken Seite kopiert.- Die Variablen auf der linken Seite müssen nicht zwingend in der gleichen Reihenfolge stehen wie auf der rechten Seite,
- sie müssen lediglich gleich heissen.
- Auf der linken Seite sieht
a: onevielleicht noch verwirrend aus, vor allem wenn du bereits TypeScript kennst.- Das bedeutet aber nur, dass du die Variable
avon der rechten Seite in eine Variable mit einem anderen Namenonekopierst. - Folglich hast du eine Variable
onedeklariert und zugewiesen. - Eine Variable
ahast du hier aber NICHT deklariert.
- Das bedeutet aber nur, dass du die Variable
- Anschliessend gibst du die Werte von
one,bunddmitconsole.log(one, b, d);aus.- Hätten wir versucht, eine Variable
aauszugeben, hätte das einen Fehler verursacht, weil keine solche Variable definiert wurde.
- Hätten wir versucht, eine Variable