var
Vor dem Erscheinen von ES6 wurden Variablen lediglich mit var
deklariert.
Dieser Weg führt jedoch oft zu Problemen, die vor allem bei Programmen mit langem Code, an dem dann vielleicht noch mehrere Personen arbeiten, auftreten.
Aus diesem Grund war es notwendig, neue Varianten zur Deklaration von Variablen zu entwickeln. Lasst uns zuerst var
besser verstehen, bevor wir diese Probleme diskutieren.
Geltungsbereich (scope) mit var
Geltungsbereich oder scope bedeutet im Wesentlichen, wo diese Variablen zur Verwendung verfügbar sind.
Deklarationen mit var
sind global oder funktions-begrenzt.
Der Geltungsbereich ist global (global scope), wenn eine Variable mit var
außerhalb einer Funktion deklariert wird. Das bedeutet, dass jede Variable, die außerhalb eines Funktionsblocks mit var
deklariert ist, im gesamten JavaScript Programm zur Verfügung steht.
var
ist funktionsbezogen (function scope), wenn es innerhalb einer Funktion deklariert wird. Dies bedeutet, dass es nur innerhalb dieser Funktion verfügbar ist und nicht außerhalb der Funktion darauf zugegriffen werden kann.
Beispiel:
var foo = 'Lorem ipsum';
function myFunction() {
var bar = 'Dolor sit amet';
}
console.log(bar); // Uncaught ReferenceError: bar is not defined
Wir bekommen also eine Fehlermeldung, da die Variable bar
nicht ausserhalb der Funktion myFunction
vorhanden ist.
Die Variable foo
hat hier einen global scope, weil sie außerhalb einer Funktion deklariert wurde.
Die Variable bar
hingegen hat einen function scope. Wir können sie nicht außerhalb der Funktion myFunction
nutzen.
Variablen, die mit var
deklariert wurden, können neu deklariert und aktualisiert werden
Dies bedeutet, dass wir folgendes im selben scope tun können ohne einen Fehler zu erhalten:
var foo = 'Lorem ipsum';
var foo = 'Dolor sit amet';
Und dies funktioniert ebenfalls:
var foo = 'Lorem ipsum';
foo = 'Dolor sit amet';
Hoisting im Zusammenhang mit var
In JavaScript können Variablen genutzt werden, bevor sie deklariert wurden. Variablen- und Funktionsdeklarationen werden dann vor der Ausführung des Codes an den Anfang ihres Gültigkeitsbereiches verschoben. Dies wird Hoisting genannt.
Folgende zwei Beispiele haben das selbe Ergebnis:
foo = 14;
console.log(foo);
var foo;
var foo;
foo = 14;
console.log(foo);
An folgendem Beispiel können wird sehen, dass mit var
deklarierte Variablen an den Anfang verschoben und mit dem Wert undefined
initialisiert werden.
console.log(foo);
var foo = 'bar';
Wir erhalten nicht die Fehlermeldung ReferenceError: foo is not defined
, sondern es wird undefined
ausgegeben.
Das Problem mit var
Es gibt ein Problem mit var
, welches im folgenden Beispiel veranschaulicht werden soll:
var foo = 'bar';
var bar = 7;
if (bar > 2) {
var foo = 'baz';
}
console.log(foo); // 'baz'
Weil die Variable bar
hier größer als 2
ist, wird die Variable foo
neu definiert.
Dies ist zwar kein Problem, wenn man wissentlich möchte, dass foo
neu definiert wird, aber es wird zu einem Problem, wenn man nicht erkennt, dass bereits zuvor eine Variable foo
definiert wurde und jetzt in ihrem scope überschrieben wird.
Wenn du die Variable foo
bereits in anderen Teilen deines Codes verwendet hast, wirst du möglicherweise von der Ausgabe überrascht sein, die du erhältst.
Dies kann zu Fehlern im Code führen, vor allem, wenn dieser lang und verschachtelt ist oder mehrere Personen an dem selben Projekt arbeiten.
Aus diesem Grund sind let
und const
mit ES6 neu hinzugekommen.
let
let
wird nun für die Deklaration von Variablen bevorzugt genutzt.
Es löst das Problem von var
, welches wir gerade behandelt haben.
Warum, sehen wir im Folgenden:
let
ist block scoped
Ein Block is ein Teil des Codes, welcher duch {}
vom Rest abgegrenzt ist.
Alles innerhalb geschweifter Klammern ist ein Block.
Eine in einem Block mit let
deklarierte Variable ist also nur für die Verwendung innerhalb dieses Blocks verfügbar.
Hierzu ein Beispiel:
let foo = 'Lorem ipsum';
let bar = 4;
if (bar > 2) {
let baz = 'Dolor sit amet';
console.log(baz); // "Dolor sit amet"
}
console.log(baz); // Uncaught ReferenceError: baz is not defined
Wir sehen also, dass wir baz
nicht außerhalb seines Blocks nutzen können, sondern uns ein Fehler ausgegeben wird.
Der Grund dafür ist, dass mit let
deklarierte Variablen einen sogenannten block scope haben.
Variablen, die mit let
deklariert wurden, können aktualisiert aber nicht neu deklariert werden
Genau wie var
kann eine mit let
deklarierte Variable innerhalb ihres scopes aktualisert werden.
Im Gegensatz zu var
kann eine mit let
deklarierte Variable jedoch nicht innerhalb ihres scopes erneut deklariert werden.
Folgendes funktioniert:
let foo = 'Lorem ipsum';
foo = 'Dolor sit amet';
Wohingegen hier ein Fehler auftritt:
let foo = 'Lorem ipsum';
let foo = 'Dolor sit amet'; // Uncaught SyntaxError: Identifier 'foo' has already been declared
Wenn jedoch die selbe Variable in verschiedenen scopes definiert wird, tritt kein Fehler auf:
let foo = 'Lorem ipsum';
let bar = 4;
if (bar > 2) {
let foo = 'Dolor sit amet';
console.log(foo); // "Dolor sit amet"
}
console.log(foo); // "Lorem ipsum"
Warum gibt es hier keinen Fehler? Dies liegt daran, dass beide Instanzen foo
als unterschiedliche Variablen behandelt werden, da sie unterschiedliche Gültigkeitsbereiche (scopes) haben.
Diese Tatsache macht let
zu einer besseren Wahl als var
.
Wenn man let
verwendet, muss man sich nicht darum kümmern, ob man zuvor einen Namen für eine Variable verwendet hat, da eine Variable nur innerhalb ihres scopes existiert.
Zusätzlich ist es von Vorteil, dass eine Variable, die mit let
deklariert wurde, nicht mehr als einmal deklariert werden kann.
Hoisting im Zusammenhang mit let
Genau wie var
werden Deklarationen bei let
an den Anfang ihres Gültigkeitsbereiches verschoben (Hoisting).
Im Gegensatz zu var
, das Variablen als undefiniert
initialisiert, wird die Variable bei let
jedoch nicht initialisiert.
Wenn man also versuchen, eine Variable, die mit let
deklariert wurde, vor der Deklaration zu verwenden, erhält man eine Fehlermeldung.
const
Variablen, die mit const
deklariert wurden, behalten konstante Werte bei. const
-Deklarationen haben einige Ähnlichkeiten mit let
-Deklarationen.
const
ist block scoped
Genau wie bei let
kann auf Variablen, die mit const
deklariert wurden, nur innerhalb ihres Blocks zugegriffen werden.
Variablen, die mit const
deklariert wurden, können weder aktualisiert noch neu deklariert werden
Das bedeutet, dass der Wert einer mit const
deklarierten Variablen innerhalb ihres scopes gleich bleibt.
Er kann nicht aktualisiert oder neu deklariert werden.
Folgendes ist also nicht möglich:
const foo = 'Lorem ipsum';
foo = 'Dolor sit amet'; // Uncaught TypeError: Assignment to constant variable
Eine Neudeklaration ist ebenfalls nicht möglich:
const foo = 'Lorem ipsum';
const foo = 'Dolor sit amet'; // Uncaught SyntaxError: Identifier 'foo' has already been declared
Jede Deklaration von Variablen mit const
muss daher zum Zeitpunkt der Deklaration initialisiert werden.
Das Verhalten ist jedoch etwas anders, wenn es um mit const
deklarierte Objekte geht.
Während ein konstantes Objekt nicht aktualisiert werden kann, können die Eigenschaften dieses Objekts jedoch wohl aktualisiert werden.
Wenn wir also ein konstantes Objekt wie folgt deklarieren:
const foo = {
bar: 'Lorem ipsum',
baz: 14
}
Können wir folgendes nicht tun:
foo = {
bar: 'Dolor sit amet',
baz: 'consetetur sadipscing elitr'
}
// Uncaught TypeError: Assignment to constant variable
Dies ist jedoch möglich:
foo.bar = 'consetetur sadipscing elitr';
Der Wert von foo.bar
wird aktualisiert, ohne das ein Fehler auftritt.
Hoisting im Zusammenhang mit const
Genau wie bei let
werden Variablen, die mit const
deklariert wurden, nach oben gehoben, aber nicht initialisiert.
Zusammenfassung
- Mit
var
deklarierte Variablen haben einen globalen oder funktioinsbezogenen scope, wohingegen mitlet
oderconst
deklarierte Variablen einen blockbezogenen scope haben. var
-Variablen können innerhalb ihres scopes aktualisiert und neu deklariert werden;let
-Variablen können aktualisiert, aber nicht neu deklariert werden;const
-Variablen können weder aktualisiert noch neu deklariert werden.- In allen drei Fällen, wird die Deklaration an den Anfang des Gültigkeitsbereiches verschoben. Aber während
var
-Variablen mitundefined
initialisiert werden, werdenlet
- undconst
-Variablen nicht initialisiert. - Während Variablen mit
var
undlet
ohne Initialisierung deklariert werden können, muss eine Variable mitconst
während der Deklaration initialisiert werden.