Javascript Variablen mit let
Die Deklaration von Variablen mit let oder const hat das alte Schlüsselwort var abgelöst. Variablen, die mit let oder const deklariert werden, gelten nur innerhalb ihres Blocks, während der Gültigkeitsbereich von Variablen mit var nur auf Funktionen eingeschränkt war. var ist zwar komfortabel, aber in großen Projekten schnell eine abgrundtiefe Fehlerquelle.
Variablen mit let statt var
Mit Javascript ES6 ist das Schlüsselwort let aufgetaucht. let ermöglicht eine neue Form des Abkapseln von Variablen und bringt eine Programmierpraxis, die es bislang in Javascript nicht gab: Block Scope – den Gültigkeitsbereich einer Variablen auf einen Block {} beschränken.
Bislang galt in Javascript nur die Beschränkung auf den Gültigkeitsbereich von Funktionen. Variablen, die mit var in einer Funktion angelegt werden, gelten nur innerhalb der Funktion. Das schützt Variablen vor versehentlichem Überschreiben.
Was ist aller Welt war so schlimm an var, dass wir jetzt let und const vorziehen?
if-Abfragen: let vs var
Eine der klassischen Fallen hinter der Definition von Variablen mit var lauert innerhalb einer if-Abfrage.
var condition = false; function foo(condition) { if (condition) { var a = 4; // Gültigkeitsbereich von a ist die Funktion foo let b = 5; // Gültigkeitsbereich von b ist der Block der if-Abfrage } var c = a + 17; } foo(condition);
Ist die Bedingung nicht erfüllt, ist a nach der if-Abfrage undefined und das Ergebnis von Berechnungen, die auf a aufbauen, liefert NaN. Das Skript läuft ohne Warnung munter weiter. Die mit let deklarierte Variable hingegen würde in jedem Fall nach der if-Abfrage zu einem sofort sichtbaren Syntaxfehler führen.
for let i=0
Obwohl der Scope oder Gültigkeitsbereich von var hier nicht auf den for-Block beschränkt ist, ist for (var i=0 … ) ein oft genutztes Muster.
for (var i=0; i<10; i++) { // .. }
Mit diesem Muster wollen Programmierer eine Variable nur für einen kleinen abgegrenzten Bereich definierten (und als solche kennzeichnen), auch wenn ihnen bewußt ist, dass var i »nach oben gehoben« wird und oberhalb des for-Blocks gilt. var i signalisiert, dass i tatsächlich nur innerhalb des for-Blocks benutzt werden soll.
Aber wer ist hierauf nicht schon einmal reingefallen?
var buttons = document.querySelectorAll("button"); for (var i=0; i<buttons.length; i++) { buttons[i].onclick = function() { console.log ("Button " + i); } }
Egal welcher Button den Klick abbekommt, die Ausgabe liefert immer dasselbe letzte i der for-Anweisung. Das Event muss als Argument in der anonymen Funktion aufgeführt werden und der angeklickte Button in der Funktion mühsam durch das Event Target identifiziert werden.
Mit for (let i=0 … ) hingegen sagt i, welcher Button geklickt wurde.
let buttons = document.querySelectorAll("button"); for (let i=0; i<buttons.length; i++) { buttons[i].onclick = function() { console.log ("Button " + i); } }
let-Variablen in for-loops werden automatisch getrennt an jede Iteration gebunden. Das galt allerdings nicht für IE11. Im Großen und Ganzen unterstützte IE 11 zwar let, aber Variablen wurde in IE11 nicht getrennt an jeden Durchlauf der for-Schleife gebunden.
Block-Scope
Vor ES6 haben Blöcke von geschweiften Klammern in Javascript keinen Scope oder Gültigkeitsbereich gebildet. Scope ist die Bezeichnung für die Umgebung, in der eine Variable gilt. Den einzigen Scope bildeten bis ES5 Javascript-Funktionen. Darum sehen wir rund um den Quelltext von Libraries – z.B. jQuery – Self Executing Functions oder selbst ausführenden Funktionen.
(function () { // script code } () );
Mit ECMAScript 6 sind Variablen, die mit let oder const definiert wurden, nur innerhalb ihres Blocks in geschweiften Klammern bekannt, und können außerhalb ihres Geltungsbereichs nicht durch Variablen mit demselben Namen überschrieben werden.
{ let x = 1; console.log(x); { let x = 2; console.log(x) }; console.log(x); }
Ausgabe
1 2 1
Ob das immer gut lesbar ist, ist eine andere Frage … .
Hoisting oder Anheben
Anheben oder Hoisting bedeutet, dass Variablen automatisch im Hintergrund an den Anfang ihres Scopes gehoben werden, Funktionen automatisch vor ihren ersten Aufruf, damit sie beim Aufruf definiert sind.
// So steht's im Script
foo ();
function foo () {
var bar = 2;
if (bar > 1 | midi) {
bar nat = bar * 10;
}
var midi = (nat * 2) + 2;
console.log (midi);
}
// So wirkt Hoisting
function foo () {
var bar, midi, nat;
bar = 2;
if (bar > 1 | midi) {
bar nat = bar * 10;
}
midi = (nat * 2) + 2;
console.log (midi);
}
foo ();
Mit ECMAScript 6 werden Variablen mit let nicht mehr automatisch an den Anfang des Blocks gehoben. Wird eine Variable vor ihrer Definition angesprochen, gibt's einen ReferenceError. Bevor eine Variable definiert wird, liegt sie in einem temporalen schwarzen Loch.