nDieser Artikel ist Teil einer Serie:n
- n
- ES6 im Überblickn
- Block Scope und Konstantenn
- Maps, Sets und Weak Mapsn
- Generatorsn
- Rest, Spread und Defaultsn
- Promisesn
n
nn
nAnders als im ECMAScript 5 rüstet ES6 nicht nur hier und da ein paar Funktionen nach, sondern bietet für viele Neuerungen neue Syntax und Konzepte, wobei einschränkend gesagt werden muss, dass viele der „Neuheiten“ so neu gar nicht sind. Das Meiste ist irgendwo geklaut: aus proprietären Browser-Erweiterungen, aus CoffeeScript, anderen Programmiersprachen oder gar aus dem gescheiterten ES4-Standard. In diese Kategorie der nicht ganz so neuen Neuheiten fallen auch die neuen blockgebundenen Variablen (let
) und Konstanten (const
), um die es in diesem Artikel geht. Die neuen Features funktionieren zur Zeit in allem, was auf neuere V8-Engines aufsetzt, also Chrome und Node, wobei es nicht mehr lange dauern dürfte, bis auch andere JS-Implementierungen nachrüsten. Wenn es endlich so weit ist, haben die JavaScript-Programmierer dieser Welt zwei Probleme mit Variablen weniger.nn
Zwei Probleme mit Variablen
nn
nProblem Nummer 1 ist, dass in ECMAScript 5 und älter der Geltungsbereich von Variablen die Funktion ist, in der sie deklariert wurden. Wenn man den folgenden Schnipsel ausführt …nn
function foobar(foo){n if(foo){n var bar = 42;n }n};
nn
n… wird der Code interprtiert, als hätte man das folgende geschrieben:nn
function foobar(foo){n var bar;n if(foo){n bar = 42;n }n};
nn
nDieses Verhalten bringt es mit sich, dass man, wenn man Variablen innerhalb von Blöcken deklariert, damit auch die Umwelt außerhalb der Blöcke verunreinigt:nn
function foobar(foo){n if(foo){n var bar = 42;n }n // "bar" ist hier auch noch 42n};
nn
nDas mag zwar in vielen Fällen wie dem obrigen nicht groß stören, in anderen hingegen schon:nn
var bar = { 'hallo': 1337 };nnfunction foobar(foo){n if(bar[foo]){n return bar[foo];n }n else {n var bar = 42 * 666;n return bar;n }n};nnvar x = foobar('hallo'); // Na, wer weiß was hier passiert?
nn
nSelbst wenn dieses Verhalten nicht oft zu Problemen führt, so ist es doch weder ist es sonderlich intuitiv, noch wird es wirklich gebraucht. Im Gegenzug ist es recht mühsam, in ECMAScript 5 und älter Variablen auf Blöcke zu beschränken, denn außer sofort ausgeführten Funktionen hilft hier nichts:nn
function foobar(foo){n whatever();n if(foo){n (function(){n var bar = 42;n })();n }n // "bar" ist hier undefinedn};
nn
nDas funktioniert zwar, ist aber der Code-Eleganz nicht besonders zuträglich und für alle mit eher mittlguten JavaScript-Kenntnissen unnötig verwirrend. nn
nDas zweite Problem ist, dass es in ECMAScript 5 und älter eben nur Variablen und keine Konstanten gibt. Es existieren zwar Konventionen, gemäß derer man Variablen durch Allcaps-Namen als „Konstanten“ kennzeichnet, doch das allein hält im Zweifelsfall niemanden davon ab, die „Konstante“ zu überschreiben:nn
var KONSTANTE = 42;nnKONSTANTE = 1337; // Funktioniert!
nn
nDie einzige in ES5 denkbare Lösung besteht darin, mittels Property Descriptor die gewünschte Konstante als nicht-überschreibbare Eigenschaft auf einem Objekt anzulegen:nn
Object.defineProperty(window, 'KONSTANTE', {n writable: false,n enumerable: true,n configurable: false,n value: 42n});nnKONSTANTE = 1337; // TypeError: Cannot assign to read only property 'KONSTANTE'
nn
nAuch hier gilt: das funktioniert zwar, aber als ersthafte Lösung kann man dieses Konvolut wohl niemandem verkaufen. ECMAScript 6 schafft nun die Probleme rund um Konstranten und var
aus der Welt, indem mit let
und const
zwei Alternativ-Formen von Variablen eingeführt werden.nn
Lösung 1: let
statt var
nn
nVerwendet man zur Deklaration einer neuen Variable das Schlüsselwort let
statt var
, so erhält man eine an den Block gebundene Variable, die jenseits ihrer Schleife oder Kontrollstruktur nicht sichtbar ist. Damit bleiben zum Beispiel die Zähler einer For-Schleife ausschließlich innerhalb der Schleife gültig:nn
for(let i = 0; i < 4; i++){n}nconsole.log(i); // ReferenceError: i is not defined
nn
nHierfür braucht es nicht zwingend echte Kontrollstrukturen oder Schleifen, auch bei leeren Blöcken funktioniert let
:nn
{n let i = 42;n}nconsole.log(i); // ReferenceError: i is not defined
nn
nAus der Blockbindung folgt, dass let
-Deklarationen nur in einem Block, in Funktionscode oder auf Programmebene vorkommen dürfen:nn
if(true) var i = 42; // Klapptnif(true) let i = 42; // SyntaxError: Illegal let declaration in unprotected statement contextnif(true){ let i = 42; } // Klappt
nn
nAnsonsten verhält sich let
ziemlich genau wie var
und unterliegt auch den gleichen Einschränkungen – auch let window = 42
kann in einem Browser das Window-Objekt nicht überschreiben. Insgesamt ist let
also nichts weiter als ein repariertes var
, dass im JavaScript-Code der Zukunft ersteres in den meisten Fällen anstelle von var
ersetzt werden dürfte.nn
Lösung 2: const
statt var
n
nMit const
lassen sich echte Konstanten anlegen, die auch wirklich nicht überschrieben werden können:nn
const KONSTANTE = 42;nKONSTANTE = 1337; // TypeError: Cannot assign to read only property 'KONSTANTE'
nn
nGenau wie let
-Variablen sind auch const
-Konstanten an ihren Block gebunden:nn
if(true){n const KONSTANTE = 42;n}nconsole.log(KONSTANTE); // ReferenceError: KONSTANTE is not defined
nn
nAnders als Variablen (egal ob let
oder var
) müssen Konstanzen logischerweise auch immer mit einem Wert initialisiert werden:nn
var foo; // Kein Problemnlet bar; // Kein Problemnconst BAZ; // SyntaxError: Unexpected token ;
nn
nAuch wenn JavaScript nun echte Konstanten kennt, ist es sinnvoll, auch bei deren Verwendung weiterhin den Bezeichner komplett groß zu schreiben – so ist immer klar, wann man es mit einer Variablen oder einer Konstanten zu tun hat.nn
Der Status
nn
nÜber let
und const
besteht in der ES6-Arbeitsgruppe weitgehend Konsens und die noch offenen Fragen (nachzulesen auf den entsprechenden Wiki-Seiten) betreffen allesamt Sonderfälle. Aufhalten lassen werden sich diese Features nicht mehr. Und so zeigt die allmächtige Kompatibilitätstabelle schon recht viel grün, doch echte Unterstützung für let
und const
findet sich zur Zeit nur in den V8-Engines von Chrome ab Version 18 und Node.js. Ab Firefox Version 2.0 sowie einigen anderen Browsern existieren auch Implementierungen von let
und const
, die jedoch nicht mit dem ES6-Standard kompatibel sind und die man daher weiträumig umfahren sollte.
Schreibe einen Kommentar