Var, let oder const? Variable Scope Issues und ES6

Bereiche in JavaScript waren schon immer ein heikles Thema, insbesondere im Vergleich zu streng organisierten Sprachen wie C und Java. Viele Jahre lang wurde der Anwendungsbereich von JS nicht besonders ausführlich diskutiert, da die Sprache einfach keine Mittel hatte, die die aktuelle Situation wesentlich beeinflussen würden. In ECMAScript 6 gibt es jedoch einige neue Funktionen, mit denen Entwickler den Umfang von Variablen besser steuern können. Diese Funktionen werden jetzt von Browsern sehr gut unterstützt und sind für die meisten Entwickler gut zugänglich. Neue Schlüsselwörter zum Deklarieren von Variablen unter Berücksichtigung der Tatsache, dass das alte Schlüsselwort var nicht verschwunden ist, bedeuten jedoch nicht nur neue Möglichkeiten, sondern auch das Auftreten neuer Fragen. Wann sollten die Schlüsselwörter let und const ? Wie verhalten sie sich? In welchen Situationen ist das Schlüsselwort var noch relevant? Das Material, dessen Übersetzung wir heute veröffentlichen, zielt darauf ab, das Problem des Umfangs von Variablen in JavaScript zu untersuchen.



Variable Bereiche: Ein Überblick


Der Umfang einer Variablen ist ein wichtiges Konzept in der Programmierung, das jedoch einige Entwickler, insbesondere Anfänger, verwirren kann. Der Bereich einer Variablen ist der Teil des Programms, in dem auf diese Variable zugegriffen werden kann.

Schauen Sie sich das folgende Beispiel an:

 var myVar = 1; function setMyVar() { myVar = 2; } setMyVar(); console.log(myVar); 

Was wird die console.log Methode ausgeben? Die Antwort auf diese Frage wird niemanden überraschen: Sie wird 2 ausgeben. Die Variable myVar außerhalb einer Funktion deklariert, die uns mitteilt, dass sie im globalen Bereich deklariert ist. Daher kann jede im selben Bereich deklarierte Funktion auf myVar zugreifen. Wenn es um Code geht, der in einem Browser ausgeführt wird, haben sogar Funktionen, die in anderen mit der Seite verbundenen Dateien deklariert sind, Zugriff auf diese Variable.

Schauen Sie sich nun den folgenden Code an:

 function setMyVar() { var myVar = 2; } setMyVar(); console.log(myVar); 

Äußerlich sind seine Änderungen im Vergleich zum vorherigen Beispiel unbedeutend. Wir haben nämlich nur die Variablendeklaration in die Funktion eingefügt. Was wird console.log jetzt ausgeben? In der Tat nichts, da diese Variable nicht deklariert ist und wenn Sie versuchen, darauf zuzugreifen, wird eine Meldung über einen nicht behandelten ReferenceError Fehler angezeigt. Dies geschah, weil die Variable innerhalb der Funktion mit dem Schlüsselwort var deklariert wurde. Infolgedessen ist der Bereich dieser Variablen auf den inneren Bereich der Funktion beschränkt. Im Hauptteil dieser Funktion kann darauf zugegriffen werden. Funktionen, die in diese Funktion eingebettet sind, können damit arbeiten, sind jedoch von außen nicht zugänglich. Wenn wir mehrere Funktionen auf derselben Ebene benötigen, um eine bestimmte Variable zu verwenden, müssen wir diese Variable an derselben Stelle deklarieren, an der diese Funktionen deklariert sind, dh eine Ebene höher als ihr interner Bereich.

Hier ist eine interessante Beobachtung: Der Code der meisten Websites und Webanwendungen gilt nicht für die Arbeit eines Programmierers. Die meisten Softwareprojekte sind das Ergebnis der Teamentwicklung und verwenden außerdem Bibliotheken und Frameworks von Drittanbietern. Selbst wenn nur ein Programmierer an der Entwicklung einer Website beteiligt ist, verwendet er normalerweise externe Ressourcen. Aus diesem Grund wird normalerweise nicht empfohlen, Variablen im globalen Bereich zu deklarieren, da Sie nicht im Voraus wissen können, welche Variablen von anderen Entwicklern deklariert werden, deren Code im Projekt verwendet wird. Um dieses Problem zu umgehen , können Sie einige Tricks anwenden, insbesondere das " Modul " -Muster und IIFE, wenn Sie den objektorientierten Ansatz auf die JavaScript-Entwicklung anwenden, obwohl die Kapselung von Daten und Funktionen in gewöhnlichen Objekten den gleichen Effekt erzielen kann. Im Allgemeinen kann festgestellt werden, dass Variablen, deren Umfang über das hinausgeht, was sie benötigen, normalerweise ein Problem darstellen, mit dem etwas getan werden muss.

Var-Schlüsselwortproblem


Also haben wir das Konzept des "Umfangs" herausgefunden. Kommen wir nun zu komplexeren Dingen. Sehen Sie sich den folgenden Code an:

 function varTest() { for (var i = 0; i < 3; i++) {   console.log(i); } console.log(i); } varTest(); 

Was wird nach der Ausführung an die Konsole gelangen? Es ist klar, dass die Werte des ansteigenden Zählers i : 0 , 1 und 2 innerhalb der Schleife angezeigt werden. Nach dem Ende der Schleife läuft das Programm weiter. Jetzt versuchen wir, auf dieselbe Zählervariable zuzugreifen, die in der for Schleife außerhalb dieser Schleife deklariert wurde. Was wird daraus?

Nach dem Aufruf von i außerhalb der Schleife gelangt 3 in die Konsole, da das Schlüsselwort var auf Funktionsebene wirkt. Wenn Sie eine Variable mit var deklarieren, können Sie in einer Funktion darauf zugreifen, auch nachdem Sie die Konstruktion verlassen haben, in der sie deklariert wurde.

Dies kann zu einem Problem werden, wenn Funktionen komplexer werden. Betrachten Sie das folgende Beispiel:

 function doSomething() { var myVar = 1; if (true) {   var myVar = 2;   console.log(myVar); } console.log(myVar); } doSomething(); 

Was wird jetzt zur Konsole gelangen? 2 und 2 . Wir deklarieren eine Variable, initialisieren sie mit der Nummer 1 und versuchen dann, dieselbe Variable in der if neu zu definieren. Da diese beiden Deklarationen im selben Bereich existieren, können wir keine neue Variable mit demselben Namen deklarieren, obwohl wir offensichtlich genau das tun möchten. Infolgedessen wird die erste Variable in der if überschrieben.

Dies ist genau der größte Fehler des Schlüsselworts var . Der Umfang der damit deklarierten Variablen ist zu groß. Dies kann zu versehentlichem Überschreiben von Daten und anderen Fehlern führen. Große Sichtbereiche führen häufig zu ungenauen Programmen. Im Allgemeinen sollte eine Variable einen Umfang haben, der durch ihre Bedürfnisse begrenzt ist, diese jedoch nicht überschreitet. Es wäre schön, Variablen deklarieren zu können, deren Umfang nicht so groß ist wie bei Verwendung von var , was es bei Bedarf ermöglichen würde, stabilere und fehlerfreiere Softwarekonstrukte zu verwenden. Tatsächlich bietet uns ECMAScript 6 solche Möglichkeiten.

Neue Möglichkeiten zum Deklarieren von Variablen


Der ECMAScript 6-Standard (ein neuer Satz von JavaScript-Funktionen, auch bekannt als ES6 und ES2015) bietet zwei neue Möglichkeiten, Variablen zu deklarieren, die sich im Vergleich zu var im Umfang unterscheiden und über einige weitere Funktionen verfügen. Dies sind die Schlüsselwörter let und const . Beide geben uns den sogenannten Blockumfang. Dies bedeutet, dass der Umfang ihrer Verwendung auf einen Codeblock beschränkt werden kann, z. B. eine for Schleife oder eine if . Dies gibt dem Entwickler mehr Flexibilität bei der Auswahl des Variablenbereichs. Betrachten Sie die neuen Schlüsselwörter.

▍Verwendung des Schlüsselworts let


Das Schlüsselwort let ist var sehr ähnlich, der Hauptunterschied ist der begrenzte Umfang der damit deklarierten Variablen. Wir schreiben eines der obigen Beispiele neu und ersetzen var durch let :

 function doSomething() { let myVar = 1; if (true) {   let myVar = 2;   console.log(myVar); } console.log(myVar); } doSomething(); 

In diesem Fall gelangen die Nummern 2 und 1 zur Konsole. Dies liegt daran, dass die if einen neuen Bereich für die mit dem Schlüsselwort let deklarierte Variable festlegt. Dies führt dazu, dass die zweite deklarierte Variable eine völlig unabhängige Entität ist, die nicht mit der ersten verwandt ist. Sie können unabhängig voneinander mit ihnen arbeiten. Dies bedeutet jedoch nicht, dass verschachtelte Codeblöcke wie unsere if vollständig von Variablen abgeschnitten sind, die mit dem Schlüsselwort let in dem Bereich deklariert wurden, in dem sie sich befinden. Sehen Sie sich den folgenden Code an:

 function doSomething() { let myVar = 1; if (true) {   console.log(myVar); } } doSomething(); 

In diesem Beispiel erhält die Konsole die Nummer 1 . Der Code in der if hat Zugriff auf die Variable, die wir außerhalb erstellt haben. Daher wird der Wert in der Konsole angezeigt. Und was passiert, wenn Sie versuchen, den Bereich zu mischen? Gehen Sie zum Beispiel folgendermaßen vor:

 function doSomething() { let myVar = 1; if (true) {   console.log(myVar);   let myVar = 2;   console.log(myVar); } } doSomething(); 

Es scheint, dass der erste Aufruf von console.log 1 ausgibt. Wenn Sie jedoch versuchen, diesen Code auszuführen, wird ein ReferenceError Fehler myVar , der besagt, dass die Variable myVar für diesen Bereich nicht definiert oder nicht initialisiert ist (der Text dieses Fehlers unterscheidet sich unterschiedlich Browser). In JavaScript gibt es so etwas wie das Anheben von Variablen an die Spitze ihres Bereichs. Das heißt, wenn eine Variable in einem bestimmten Bereich deklariert wird, reserviert JavaScript einen Platz dafür, noch bevor der Befehl zum Deklarieren ausgeführt wird. Wie genau dies geschieht, ist bei Verwendung von var und let .

Betrachten Sie das folgende Beispiel:

 console.log(varTest); var varTest = 1; console.log(letTest); let letTest = 2; 

In beiden Fällen versuchen wir, die Variable zu verwenden, bevor wir sie deklarieren. Konsolenausgabebefehle verhalten sich jedoch anders. Die erste, die eine Variable verwendet, die später mit dem Schlüsselwort var deklariert wird, gibt undefined - das heißt, was in diese Variable geschrieben wird. Der zweite Befehl, der versucht, auf die Variable zuzugreifen, die später mit dem Schlüsselwort let deklariert wird, löst einen ReferenceError und teilt uns mit, dass wir versuchen, die Variable zu verwenden, bevor sie deklariert oder initialisiert wird. Was ist los?

Tatsache ist jedoch, dass die für seine Ausführung verantwortlichen Mechanismen vor der Ausführung des Codes diesen Code untersuchen, herausfinden, ob darin Variablen deklariert werden, und sie in diesem Fall unter Vorbehalt von Speicherplatz für sie auslösen. In diesem Fall werden Variablen, die mit dem Schlüsselwort var deklariert wurden, innerhalb ihres Gültigkeitsbereichs auf undefined initialisiert, selbst wenn auf sie zugegriffen wird, bevor sie deklariert werden. Das Hauptproblem hierbei ist, dass der undefined Wert in einer Variablen nicht immer anzeigt, dass sie versuchen, die Variable vor ihrer Deklaration zu verwenden. Schauen Sie sich das folgende Beispiel an:

 var var1; console.log(var1); console.log(var2); var var2 = 1; 

In diesem Fall var2 beide Aufrufe von console.log undefined ausgegeben, obwohl var1 und var2 unterschiedlich var2 . Der Punkt hier ist, dass in Variablen, die mit var deklariert, aber nicht initialisiert wurden, der undefined Wert automatisch geschrieben wird. Gleichzeitig enthalten, wie bereits erwähnt, mit var deklarierte Variablen, auf die zugegriffen wird, bevor sie deklariert werden, auch undefined . Wenn in einem solchen Code etwas schief geht, ist es daher nicht möglich zu verstehen, was genau die Fehlerquelle ist - unter Verwendung einer nicht initialisierten Variablen oder unter Verwendung einer Variablen vor ihrer Deklaration.

Der Platz für Variablen, die mit dem Schlüsselwort let deklariert wurden, ist in ihrem Block reserviert, aber bevor sie deklariert werden, fallen sie in die temporäre Totzone (TDZ, Temporal Dead Zone). Dies führt dazu, dass sie nicht verwendet werden können, bevor sie deklariert wurden, und ein Versuch, auf eine solche Variable zuzugreifen, führt zu einem Fehler. Das System kennt jedoch die Ursache des Problems genau und meldet sie. Dies ist in diesem Beispiel deutlich zu sehen:

 let var1; console.log(var1); console.log(var2); let var2 = 1; 

Hier wird beim ersten Aufruf von console.log undefined ausgegeben, und beim zweiten Aufruf wird ein ReferenceError Fehler ausgegeben, der uns mitteilt, dass die Variable noch nicht deklariert oder initialisiert wurde.

Wenn daher die Verwendung von var undefined erscheint, kennen wir den Grund für dieses Verhalten des Programms nicht. Eine Variable kann entweder deklariert und nicht initialisiert werden oder sie ist möglicherweise noch nicht in diesem Bereich deklariert, sie wird jedoch im Code unter dem Befehl deklariert, um darauf zuzugreifen. Mit dem Schlüsselwort let können wir verstehen, was genau passiert, was für das Debuggen viel nützlicher ist.

▍Verwendung des Schlüsselworts const


Das const Schlüsselwort ist let sehr ähnlich, aber sie haben einen wichtigen Unterschied. Dieses Schlüsselwort wird verwendet, um Konstanten zu deklarieren. Die Werte der Konstanten können nach ihrer Initialisierung nicht mehr geändert werden. Es ist zu beachten, dass dies nur für Werte primitiver Typen, Wasser, Zeichenfolgen oder Zahlen gilt. Wenn die Konstante etwas Komplexeres ist, z. B. ein Objekt oder ein Array, kann die interne Struktur einer solchen Entität geändert werden. Sie können sie nicht einfach durch eine andere ersetzen. Sehen Sie sich den folgenden Code an:

 let mutableVar = 1; const immutableVar = 2; mutableVar = 3; immutableVar = 4; 

Dieser Code wird bis zur letzten Zeile ausgeführt. Der Versuch, einer Konstanten einen neuen Wert zuzuweisen, führt zu einem TypeError Fehler. So verhalten sich Konstanten, aber wie bereits erwähnt, können die Objekte, die Konstanten initialisieren, geändert werden, sie können Mutationen unterliegen, was zu Überraschungen führen kann.

Vielleicht fragen Sie sich als JavaScript-Entwickler, warum die Immunität von Variablen wichtig ist. Konstanten sind ein neues Phänomen in JavaScript, während sie ein wesentlicher Bestandteil von Sprachen wie C oder Java sind. Warum ist dieses Konzept so beliebt? Tatsache ist, dass wir durch die Verwendung von Konstanten darüber nachdenken, wie unser Code funktioniert. In einigen Situationen kann das Ändern des Werts einer Variablen den Code stören, z. B. wenn die Nummer Pi darin geschrieben ist und ständig darauf zugegriffen wird oder wenn die Variable einen Link zu einem HTML-Element enthält, mit dem Sie ständig arbeiten müssen. Angenommen, hier ist eine Konstante, in die ein Link zu einer bestimmten Schaltfläche geschrieben ist:

 const myButton = document.querySelector('#my-button'); 

Wenn der Code vom Link zum HTML-Element abhängt, müssen wir die Unveränderlichkeit dieses Links sicherstellen. Infolgedessen können wir sagen, dass das Schlüsselwort const nicht nur den Weg der Verbesserungen im Bereich der Sichtbarkeit einschlägt, sondern auch die Möglichkeit einschränkt, die Werte von Konstanten zu ändern, die mit diesem Schlüsselwort deklariert wurden. Denken Sie daran, wie wir gesagt haben, dass eine Variable genau den Umfang haben sollte, den sie benötigt. Diese Idee kann fortgesetzt werden, indem eine Empfehlung abgegeben wird, wonach eine Variable nur die Fähigkeit haben sollte, sich zu ändern, was für eine ordnungsgemäße Arbeit damit erforderlich ist, und nicht mehr. Hier ist gutes Material zum Thema Immunität, aus dem eine wichtige Schlussfolgerung gezogen werden kann, wonach die Verwendung unveränderlicher Variablen uns dazu bringt, genauer über unseren Code nachzudenken, was zu einer Verbesserung der Reinheit des Codes und zu einer Verringerung der Anzahl unangenehmer Überraschungen führt, die sich aus seiner Funktionsweise ergeben.

Als ich anfing, die Schlüsselwörter let und const , habe ich im Grunde genommen let und nur dann auf const , wenn ein neuer Wert in eine mit let deklarierte Variable geschrieben wurde let die dem Programm schaden könnte. Aber als ich mehr über das Programmieren lernte, überlegte ich es mir anders. Jetzt ist mein Hauptwerkzeug const und ich kann es nur verwenden, wenn der Wert der Variablen neu geschrieben werden muss. Dies lässt mich darüber nachdenken, ob es wirklich notwendig ist, den Wert einer bestimmten Variablen zu ändern. In den meisten Fällen ist dies nicht erforderlich.

Benötigen wir das Schlüsselwort var?


Die Schlüsselwörter let und const tragen zu einem verantwortungsbewussteren Programmieransatz bei. Gibt es Situationen, in denen das Schlüsselwort var noch benötigt wird? Ja gibt es. Es gibt verschiedene Situationen, in denen dieses Schlüsselwort für uns immer noch nützlich ist. Überlegen Sie genau, worüber wir sprechen, bevor Sie var in let oder const ändern.

▍ Unterstützungsstufe für verschiedene Schlüsselwörter durch Browser


Mit dem Schlüsselwort var deklarierte Variablen haben eine sehr wichtige Funktion, die let und const fehlt. Wir sprechen nämlich von der Tatsache, dass absolut alle Browser dieses Schlüsselwort unterstützen. Obwohl die Unterstützung für let und const durch Browser sehr gut ist, besteht das Risiko, dass Ihr Programm in einem Browser landet, der sie nicht unterstützt. Um die Konsequenzen eines solchen Vorfalls zu verstehen, müssen Sie überlegen, wie Browser mit nicht unterstütztem JavaScript-Code umgehen und nicht wie sie beispielsweise auf CSS-Code reagieren, den sie nicht verstehen.

Wenn der Browser einige CSS-Funktionen nicht unterstützt, führt dies im Grunde zu einer gewissen Verzerrung der Anzeige auf dem Bildschirm. Eine Site in einem Browser, die keinen der von der Site verwendeten Stile unterstützt, sieht nicht wie erwartet aus, kann aber sehr wahrscheinlich verwendet werden. Wenn Sie beispielsweise let und der Browser dieses Schlüsselwort nicht unterstützt, funktioniert Ihr JS-Code dort einfach nicht. Es wird nicht sein - das ist alles. Angesichts der Tatsache, dass JavaScript eine der wichtigsten Komponenten des modernen Webs ist, kann dies zu einem ernsthaften Problem werden, wenn Ihre Programme in veralteten Browsern funktionieren müssen.

Wenn Leute über die Browserunterstützung für Websites sprechen, fragen sie normalerweise, in welchem ​​Browser die Website optimal funktioniert. Wenn es sich um eine Site handelt, deren Funktionalität auf der Verwendung von let und const basiert, muss eine ähnliche Frage anders gestellt werden: „In welchen Browsern funktioniert unsere Site nicht?“. Und das ist viel ernster, als darüber zu sprechen, ob display: flex oder nicht. Bei den meisten Websites ist die Anzahl der Benutzer mit veralteten Browsern nicht groß genug, um sich Sorgen zu machen. Wenn es sich jedoch um einen Online-Shop oder um Websites handelt, deren Eigentümer Werbung kaufen, kann dies eine sehr wichtige Überlegung sein. Bevor Sie in solchen Projekten neue Chancen nutzen, sollten Sie das Risikoniveau bewerten.

Wenn Sie wirklich alte Browser unterstützen müssen, aber let , const und andere neue ES6-Funktionen verwenden möchten, besteht eine der Lösungen für dieses Problem darin, einen JavaScript-Transporter wie Babel zu verwenden . Transpiler bieten die Übersetzung von neuem Code in das, was alte Browser verstehen. Mit Babel können Sie modernen Code schreiben, der die neuesten Funktionen der Sprache verwendet, und ihn dann in Code konvertieren, den ältere Browser ausführen können.

, ? , . , , , , . , . , , . ES6-, Babel, Babel , , . , , . . ? - IE8 ? , , , , , .

▍ var


, var , . . :

 var myVar = 1; function myFunction() { var myVar = 2; //  ,     myVar    ! } 

, myVar , , . , . , , , , . , . var .

 var myVar = 1; function myFunction() { var myVar = 2; console.log(myVar); // 2 console.log(window.myVar); // 1 } 

var , window . let const . , JS- , (, , ) , .

, . , . , , , :

 let myGlobalVars = {}; let myVar = 1; myGlobalVars.myVar = myVar; function myFunction() { let myVar = 2; console.log(myVar); // 2 console.log(myGlobalVars.myVar); // 1 } 

, , , , . , , var , , , , , .

Zusammenfassung


, ? ? :

  • IE10 - ? — var .
  • JavaScript, , , var , const . - (, , ) — let .

let const , ECMAScript 6, ( ) - -. , , , . , - , «» «» , , let const , .

! , const var , let , , , ?

Source: https://habr.com/ru/post/de420359/


All Articles