JavaScript/Variable/let
Mit dem Schlüsselwort let können Variablen deklariert werden, die über eine von var
abweichende Semantik verfügen. Sie sind zum Beispiel nicht grundsätzlich im gesamten, mit einem Ausführungskontext assoziierten Code sichtbar und für ihre Verwendung gelten, im Vergleich zu Variablen die mit var
deklariert werden, deutlich strengere Regeln.
Details: caniuse.com
Syntax
let name = value;
Inhaltsverzeichnis
Deklaration
Eine unter Verwendung von let deklarierte Variable kann, aber muss nicht bei ihrer Deklaration initialisiert werden. Wird ihr bei der Deklaration nicht explizit ein Wert zugewiesen, dann wird sie stattdessen automatisch mit dem primitiven Wert undefined initialisiert.
let number = 42;
console.log(number); // 42
let local;
console.log(local); // undefined
local = 'value';
console.log(local); // value
Es ist auch möglich, innerhalb einer Anweisung mehrere Variablen zu deklarieren. Dabei werden die einzelnen Deklarationen mit einem Komma getrennt, wobei es auch in diesem Fall nicht notwendig ist die Variablen direkt zu initialisieren, wie das folgende Beispiel zeigt.
let word, number = Math.PI, symbol;
[word, number, symbol].forEach(function (value) {
value && console.log(value.toFixed(3)); // 3.142
});
Ebenso wie bei Variablen die mit dem Schlüsselwort var deklariert werden und wie bei Konstanten, kann der Variable ein Wert von einem beliebigen Datentyp zugewiesen werden und es ist ebenfalls möglich einen Ausdruck zu notieren, mit dessen Wert die Variable initialisiert wird.
let object = function (parameter) {
return parameter;
}({
property : 'value'
});
console.log(object.property); // value
Der Zuweisungsausdruck (Assignment Expression) kann natürlich auch eine Referenz enthalten. Wenn jedoch ein Bezeichner referenziert wird, der zu keinem Wert aufgelöst werden kann, dann wird wie üblich eine Ausnahme geworfen und nicht etwa implizit eine entsprechende Variable angelegt oder ein Standardwert wie undefined hinterlegt.
let object = {
property : 'value'
};
let copy = object;
let name = value; // Reference Error
Dass bei einer Zuweisung eine Ausnahme geworfen wird, wenn es sich bei dem Ausdruck auf der rechten Seite um eine nicht auflösbare Referenz handelt, ist übrigens immer der Fall, unabhängig vom Ausführungsmodus des Programms oder davon, ob eine Variable mit let, mit var oder ob eine Konstante initialisiert wird. Das Gleiche gilt für die Definition von Objekteigenschaften.
const mars = ['phobos', 'deimos'];
let [first, last] = mars;
const satellites = {
earth : 'moon'
};
let {earth} = satellites;
console.log(`${first} ${last} ${earth}`); // phobos deimos moon
Schließlich kann auch bei Variablen die mit let deklariert werden die Deklaration im Zuge der Destrukturierung eines Arrays oder eines Objektes erfolgen, wobei nicht existierende Arrayelemente oder Objekteigenschaften durch den Wert undefined ersetzt werden. Dies kann anders als in dem Beispiel oben auch in einer einzelnen Anweisung erfolgen, wobei wie üblich die einzelnen Deklarationen durch Komma zu trennen sind.
Sichtbarkeit
Ebenso wie mittels const
deklarierte Konstanten und anders als mit var deklarierte Variablen, besitzen Variablen, die unter Verwendung des Schlüsselwortes let deklariert werden, Block Scope, das heißt, sie sind nur innerhalb des jeweiligen Blocks sichtbar, in dem sie deklariert wurden. Von außerhalb des Blocks können sie hingegen nicht referenziert werden.
let local = 32;
{
let local = 64;
console.log(local); // 64
}
console.log(local); // 32
In dem Beispiel oben wird zunächst im globalen Gültigkeitsbereich eine Variable mit dem Bezeichner local deklariert und mit einem Wert initialisiert. Dabei wird der Bezeichner der Variable an die lexikalische Umgebung des globalen Ausführungskontexts gebunden. Sobald der Programmfluss die öffnende geschweifte Klammer erreicht, die den Beginn eines Anweisungsblocks markiert, wird für diesen Block eine eigene lexikalische Umgebung erzeugt und die innerhalb des Blocks deklarierte Variable mit demselben Bezeichner daran gebunden. Folglich wird die Referenz, die an die Methode log innerhalb des Blocks übergeben wird, zu dem Wert der innerhalb des Blocks deklarierten Variable aufgelöst. Nachdem der Programmfluss den Scope des Blocks wieder verlassen hat, ist die zuvor durch die Variable in dem Block verschattete Variable des globalen Scopes wieder sichtbar, sodass bei dem zweiten Aufruf der Methode log entsprechend ihr Wert ausgegeben wird.
for (let index = 2; index <= 5; index ++) {
let number = Math.pow(index, 3);
console.log(number); // 8, 27, 64, 125
}
console.log(index); // Reference Error
Darüber hinaus sind Variablen die mittels let in einem Schleifenkopf deklariert werden auch nur innerhalb der Schleife sichtbar, außerhalb jedoch nicht. Das heißt, bezogen auf das Beispiel oben, kann die Zählvariable index nur im Kopf der Schleife und in deren Anweisungsblock referenziert werden, während der Versuch der Referenzierung nach verlassen der Schleife einen Fehler produziert. Die Variable number hingegen ist in ihrer Sichtbarkeit auf den Anweisungsblock beschränkt, der bei jedem Schleifendurchlauf neu initialisiert wird.
function test ( ) {
// temporal dead zone
console.log(typeof number); // Reference Error
// declaration
let number = 128;
}
test( );
Schließlich ist in diesem Zusammenhang zu beachten, dass zwar die Bindung von Variablenbezeichner und lexikalischer Umgebung beim Eintritt in den jeweiligen Gültigkeitsbereich erfolgt, aber die Variable vor ihrer Deklaration im Code nicht mit einem Standardwert initialisiert wird. Das heißt, anders als bei Variablen die mittels var deklariert werden, können mit let deklarierte Variablen, ebenso wie Konstanten, nicht vor ihrer eigentlichen Deklaration referenziert werden. Dies erzeugt immer einen Fehler, selbst dann, wenn wie in dem Beispiel oben der Operator typeof verwendet wird, da es sich hierbei nicht um eine unauflösbare Referenz, sondern lediglich um eine noch nicht initialisierte Variable handelt. Die Zeit vom Eintritt in den Gültigkeitsbereich bis zur Deklaration der Variable wird auch Temporal Dead Zone genannt.
Redeklaration
Wird innerhalb desselben Gültigkeitsbereichs mehr als einmal eine Variable mit dem Schlüsselwort let und mit demselben Bezeichner deklariert, dann wird dadurch ein Typfehler erzeugt und das Programm kann nicht ausgeführt werden. Hier verhält es sich also anders als bei Variablen die mit var deklariert werden, denn bei diesen Variablen wird ohne Fehler und ohne Warnung nur eine Variable an die lexikalische Umgebung gebunden, welcher dann gegebenenfalls durch die Redeklaration ein neuer Wert zugewiesen wird.
// Type Error before execution
let clone = 'Dolly';
let clone = 'Jango Fett';
Dabei spielt es im Übrigen aus Sicht einer mit let deklarierten Variable keine Rolle, ob eine gleichnamige Variable ebenfalls mittels let deklariert wurde oder ob es sich dabei um eine mit var deklarierte Variable handelt. Ebenso wird ein Fehler erzeugt, wenn im Scope der Variable eine Funktion mit demselben Bezeichner deklariert wurde oder wenn in einer Funktion ein formaler Parameter mit demselben Namen notiert wurde.
Verwendung
Es ist empfehlenswert, für Variablen grundsätzlich let zu verwenden und nicht var, da Variablen, die mit let deklariert werden, in ihrem Verhalten deutlich berechenbarer sind und durch die strengeren Regeln ihrer Verwendung im Vergleich ein besserer Programmierstil gefördert wird. Allerdings ist zu beachten, dass wenn eine Variable über ihre Lebenszeit hinweg immer den gleichen Wert behält, es besser ist, mittels const eine Konstante zu deklarieren, da dies dem Code etwas mehr Transparenz verleiht und es darüber hinaus Optimierungen des Programms bei dessen Interpretation ermöglicht.
const increment = value => value += 1;
let count = 0;
console.log(increment(count)); // 1
Weblinks
Let and Const Declarations | Let and Const ECMAScript 2015 | ECMAScript 2016 | ECMAScript 2017 Draft |
- MDN: let