Was ist der Unterschied zwischen der Verwendung von „let“ und „var“?
-
11-09-2019 - |
Frage
ECMAScript 6 eingeführt Die let
Stellungnahme.
Ich habe gehört, dass sie als „lokale“ Variable beschrieben wird, bin mir aber immer noch nicht ganz sicher, inwiefern sie sich anders verhält als die var
Stichwort.
Was sind die Unterschiede?Wann sollte let
übernutzt werden var
?
Lösung
Scoping-Regeln
Der Hauptunterschied ist Scoping-Regeln. Variablen von var
Schlüsselwort deklariert wird auf die unmittelbare Funktion Körper scoped (daher auch der Funktionsumfang), während let
Variablen auf die unmittelbare scoped sind umschließenden Block durch { }
bezeichnet (daher der Block scope).
function run() {
var foo = "Foo";
let bar = "Bar";
console.log(foo, bar);
{
let baz = "Bazz";
console.log(baz);
}
console.log(baz); // ReferenceError
}
run();
Der Grund, warum let
Stichwort in die Sprache eingeführt wurde, ist Funktionsumfang verwirrend ist und war einer der Hauptquelle für Fehler in Javascript.
Werfen Sie einen Blick auf dieses Beispiel von href="https://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example">:
var funcs = [];
// let's create 3 functions
for (var i = 0; i < 3; i++) {
// and store them in funcs
funcs[i] = function() {
// each should log its value.
console.log("My value: " + i);
};
}
for (var j = 0; j < 3; j++) {
// and now let's run each one to see
funcs[j]();
}
My value: 3
Ausgang war jedes Mal funcs[j]();
zu trösten aufgerufen wurde, da anonyme Funktionen auf die gleiche gleiche Variable gebunden waren.
Die Menschen mußten sofort aufgerufen Funktionen erstellen erstellen richtigen Wert aus den Schlingen zu fangen, aber das war auch behaart.
Hissen
Während Variablen mit var
Schlüsselwort deklariert werden „gehoben“ an die Spitze des Blockes, bedeutet, dass sie in ihrem umschließenden Umfang zugänglich sind, noch bevor sie deklariert werden:
function run() {
console.log(foo); // undefined
var foo = "Foo";
console.log(foo); // Foo
}
run();
lassen Variablen werden nicht initialisiert, bis ihre Definition ausgewertet wird. Zugriff auf sie, bevor die Initialisierung führt zu einer ReferenceError
. Variable, die in dem „temporal tote Zone“ zu sein, von Anfang des Blocks, bis die Initialisierung verarbeitet wird.
function checkHoisting() {
console.log(foo); // ReferenceError
let foo = "Foo";
console.log(foo); // Foo
}
checkHoisting();
Erstellen globale Objekteigenschaft
Auf der obersten Ebene, let
, im Gegensatz zu var
, schafft nicht eine Eigenschaft auf dem globalen Objekt:
var foo = "Foo"; // globally scoped
let bar = "Bar"; // globally scoped
console.log(window.foo); // Foo
console.log(window.bar); // undefined
Redeklaration
Im strikten Modus var
lassen Sie die gleiche Variable im gleichen Umfang wieder erklären, während let
eine Syntax erhöht.
'use strict';
var foo = "foo1';
var foo = "foo2'; // No problem, 'foo' is replaced.
let bar = "bar1";
let bar = "bar2"; // SyntaxError: Identifier 'bar' has already been declared
Andere Tipps
let
kann auch zur Vermeidung von Problemen mit Verschlüssen verwendet werden. Es bindet frisch Wert eher als eine alte Referenz zu halten, wie unten in den Beispielen gezeigt.
for(var i=1; i<6; i++) {
$("#div" + i).click(function () { console.log(i); });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="div1">1</div>
<div id="div2">2</div>
<div id="div3">3</div>
<div id="div4">4</div>
<div id="div5">5</div>
-Code oben zeigt ein klassisches JavaScript Schließungsproblem. Verweis auf die i
Variable wird in der Click-Handler Schließung gespeichert werden, anstatt der tatsächliche Wert des i
.
Jeder einzelne Klick-Handler wird auf das gleiche Objekt verweisen, da es nur einen Zähler Objekt ist, das 6 hält so erhalten Sie sechs auf jeden Klick.
Eine allgemeine Abhilfe ist dies in einer anonymen Funktion wickeln und i
als Argument übergeben. Solche Probleme können auch jetzt durch die Verwendung let
statt vermieden werden var
wie in dem unten stehenden Code dargestellt.
(getestet in Chrome und Firefox 50)
for(let i=1; i<6; i++) {
$("#div" + i).click(function () { console.log(i); });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="div1">1</div>
<div id="div2">2</div>
<div id="div3">3</div>
<div id="div4">4</div>
<div id="div5">5</div>
Was ist der Unterschied zwischen let
und var
?
- Eine Variable eine
var
Anweisung definiert verwendet, ist bekannt im ganzen die Funktion es in dem Start der Funktion definiert ist. * - Eine Variable eine
let
Anweisung definiert unter Verwendung ist nur bekannt, in < strong> der Block es in es weiter definiert ist von dem Moment definiert ist. **
, um den Unterschied zu verstehen, sollten Sie den folgenden Code ein:
// i IS NOT known here
// j IS NOT known here
// k IS known here, but undefined
// l IS NOT known here
function loop(arr) {
// i IS known here, but undefined
// j IS NOT known here
// k IS known here, but has a value only the second time loop is called
// l IS NOT known here
for( var i = 0; i < arr.length; i++ ) {
// i IS known here, and has a value
// j IS NOT known here
// k IS known here, but has a value only the second time loop is called
// l IS NOT known here
};
// i IS known here, and has a value
// j IS NOT known here
// k IS known here, but has a value only the second time loop is called
// l IS NOT known here
for( let j = 0; j < arr.length; j++ ) {
// i IS known here, and has a value
// j IS known here, and has a value
// k IS known here, but has a value only the second time loop is called
// l IS NOT known here
};
// i IS known here, and has a value
// j IS NOT known here
// k IS known here, but has a value only the second time loop is called
// l IS NOT known here
}
loop([1,2,3,4]);
for( var k = 0; k < arr.length; k++ ) {
// i IS NOT known here
// j IS NOT known here
// k IS known here, and has a value
// l IS NOT known here
};
for( let l = 0; l < arr.length; l++ ) {
// i IS NOT known here
// j IS NOT known here
// k IS known here, and has a value
// l IS known here, and has a value
};
loop([1,2,3,4]);
// i IS NOT known here
// j IS NOT known here
// k IS known here, and has a value
// l IS NOT known here
Hier können wir sehen, dass unsere Variable j
nur in der ersten for-Schleife bekannt ist, aber nicht vorher und nachher. Doch unser Variable i
in der gesamten Funktion bekannt.
Bedenken Sie auch, dass der Block scoped Variablen nicht bekannt sind, bevor sie deklariert werden, weil sie nicht hochgezogen werden. Sie sind auch nicht der gleiche Block scoped Variable in demselben Block zu deklarieren erlaubt. Dies macht scoped Blockvariablen weniger fehleranfällig als global oder funktionell scoped Variablen, die hochgezogen werden und die produzieren keine Fehler bei mehreren Erklärungen.
Ist es sicher let
heute zu benutzen?
Einige Leute würden argumentieren, dass wir in Zukunft nur Aussagen verwenden werden lassen und dass die var-Anweisungen werden veralten. JavaScript Guru Kyle Simpson schrieb ein sehr aufwendiger Artikel darüber, warum er, dass der Fall wird nicht glaubt.
Heute aber das ist definitiv nicht der Fall. In der Tat müssen wir tatsächlich uns fragen, ob es sicher ist, die let
Anweisung zu verwenden. Die Antwort auf diese Frage hängt von Ihrer Umgebung:
-
Wenn Sie schreiben serverseitige JavaScript-Code ( Node.js ), können Sie sicher die
let
Anweisung verwenden. -
Wenn Sie schreiben clientseitige JavaScript-Code und einen Browser-basierten Transpiler verwenden (wie < strong> Traceur oder babel-Standalone ), können Sie sicher die
let
Anweisung verwenden können, ist jedoch der Code wahrscheinlich in Bezug auf Leistung alles andere als optimal. -
Wenn Sie schreiben clientseitige JavaScript-Code und einen Knoten basierend Transpiler verwenden (wie die traceur Shell-Skript oder Babel ), können Sie sicher die
let
Anweisung verwenden. Und da Ihr Browser nur über den transpiled Code weiß, Leistung Nachteile sollen begrenzt werden. -
Wenn Sie schreiben clientseitige JavaScript-Code und nicht mit einem Transpiler, müssen Sie die Browserunterstützung berücksichtigen.
Es gibt noch einige Browser, die
let
unterstützen nicht:
Wie Spur von Browser-Unterstützung halten
Für einen up-to-date Überblick über welche Browser diese Antwort die let
Aussage zum Zeitpunkt Ihrer Lesung unterstützen, finden Sie gehisst < Diese / strong> . bedeutet, dass Erklärungen an die Spitze des Bereichs immer viel sind.
** Block scoped Variablen nicht gehisst
Hier ist ein Erklärung des let
Stichwort mit einigen Beispielen rel="nofollow.
let
funktioniert ähnlich wievar
. Der Hauptunterschied besteht darin, dass der Umfang einesvar
Variable ist die gesamte einschließende Funktion
Diese Tabelle auf Wikipedia zeigt, welche Browser unterstützt kein Javascript 1.7.
Beachten Sie, dass nur Mozilla und Chrome-Browser unterstützen. IE, Safari und möglicherweise andere nicht.
Die akzeptierte Antwort fehlt ein Punkt:
{
let a = 123;
};
console.log(a); // ReferenceError: a is not defined
let
Block Anwendungsbereich
Variablen deklariert mit dem let
Schlüsselwort block scoped, was bedeutet, dass sie nur in der Block , in dem sie deklariert wurden.
Auf der obersten Ebene (außerhalb einer Funktion)
Auf der obersten Ebene, deklarierte Variablen let
mit nicht-Eigenschaften auf dem globalen Objekt erstellen.
var globalVariable = 42;
let blockScopedVariable = 43;
console.log(globalVariable); // 42
console.log(blockScopedVariable); // 43
console.log(this.globalVariable); // 42
console.log(this.blockScopedVariable); // undefined
Innerhalb einer Funktion
Innerhalb einer Funktion (aber außerhalb eines Blocks), let
hat den gleichen Umfang wie var
.
(() => {
var functionScopedVariable = 42;
let blockScopedVariable = 43;
console.log(functionScopedVariable); // 42
console.log(blockScopedVariable); // 43
})();
console.log(functionScopedVariable); // ReferenceError: functionScopedVariable is not defined
console.log(blockScopedVariable); // ReferenceError: blockScopedVariable is not defined
Innerhalb eines Blocks
deklarierten Variablen innerhalb eines Blockes mit let
nicht außerhalb dieser Blöcke zugegriffen werden.
{
var globalVariable = 42;
let blockScopedVariable = 43;
console.log(globalVariable); // 42
console.log(blockScopedVariable); // 43
}
console.log(globalVariable); // 42
console.log(blockScopedVariable); // ReferenceError: blockScopedVariable is not defined
Innerhalb einer Schleife
Variablen mit let
in Schleifen deklariert ist, kann innerhalb dieser Schleife nur referenziert werden.
for (var i = 0; i < 3; i++) {
var j = i * 2;
}
console.log(i); // 3
console.log(j); // 4
for (let k = 0; k < 3; k++) {
let l = k * 2;
}
console.log(typeof k); // undefined
console.log(typeof l); // undefined
// Trying to do console.log(k) or console.log(l) here would throw a ReferenceError.
Loops mit Schließungen
Wenn Sie let
statt var
in einer Schleife verwenden, bei jeder Iteration Sie eine neue Variable bekommen. Das bedeutet, dass Sie sicher einen Verschluss in einer Schleife verwenden können.
// Logs 3 thrice, not what we meant.
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0);
}
// Logs 0, 1 and 2, as expected.
for (let j = 0; j < 3; j++) {
setTimeout(() => console.log(j), 0);
}
Temporal tote Zone
Aufgrund der die zeitliche Totzonen , deklarierten Variablen mit let
nicht zugegriffen werden kann, bevor sie deklariert sind. so wirft einen Fehler zu machen versucht wird.
console.log(noTDZ); // undefined
var noTDZ = 43;
console.log(hasTDZ); // ReferenceError: hasTDZ is not defined
let hasTDZ = 42;
Keine Wieder erklärt
Sie können nicht die gleiche Variable mehrfach mit let
erklären. Sie können auch nicht über eine Variable let
mit der gleichen Kennung wie eine andere Variable deklarieren, die var
deklariert wurde mit.
var a;
var a; // Works fine.
let b;
let b; // SyntaxError: Identifier 'b' has already been declared
var c;
let c; // SyntaxError: Identifier 'c' has already been declared
const
const
ist ganz ähnlich wie let
-es ist Block-scoped und hat TDZ. Es gibt jedoch zwei Dinge, die anders sind.
Keine Neuzuweisung
Variable deklariert mit const
kann nicht neu zugeordnet werden.
const a = 42;
a = 43; // TypeError: Assignment to constant variable.
Beachten Sie, dass es nicht bedeutet, dass der Wert unveränderlich ist. Seine Eigenschaften können noch geändert werden.
const obj = {};
obj.a = 42;
console.log(obj.a); // 42
Wenn Sie ein unveränderliches Objekt haben wollen, sollten Sie Object.freeze()
.
Initializer erforderlich
Sie müssen immer einen Wert angeben, wenn eine Variable mit const
deklarieren.
const a; // SyntaxError: Missing initializer in const declaration
Hier ist ein Beispiel für den Unterschied zwischen den beiden (Unterstützung habe gerade angefangen für Chrom):
Wie Sie der var j
Variable noch sehen können, ist außerhalb des for-Schleife Umfang (Block Scope) einen Wert hat, aber der let i
Variable außerhalb der for-Schleife Rahmen nicht definiert.
"use strict";
console.log("var:");
for (var j = 0; j < 2; j++) {
console.log(j);
}
console.log(j);
console.log("let:");
for (let i = 0; i < 2; i++) {
console.log(i);
}
console.log(i);
Es gibt einige feine Unterschiede - let
Scoping verhält sich eher wie variable Scoping hat in mehr oder weniger allen anderen Sprachen.
z. Es Tive zum umschließenden Block, Sie existieren nicht, bevor sie deklariert sind, etc.
Allerdings ist es erwähnenswert, dass let
ist nur ein Teil der neueren Javascript-Implementierungen und hat unterschiedliche Grade der Browser-Unterstützung .
-
Variable Nicht Hoistinglet
wird nicht hissen , um den gesamten Umfang des Blockes sie erscheinen in. Im Gegensatz dazuvar
wie unten hissen kann.{ console.log(cc); // undefined. Caused by hoisting var cc = 23; } { console.log(bb); // ReferenceError: bb is not defined let bb = 23; }
Eigentlich Per @Bergi, Beide
var
undlet
sind gehisst . -
Garbage Collection
Blockumfang
let
nützlich ist, bezieht sich auf Verschlüsse und Garbage Collection Speicher zurückzufordern. Betrachtenfunction process(data) { //... } var hugeData = { .. }; process(hugeData); var btn = document.getElementById("mybutton"); btn.addEventListener( "click", function click(evt){ //.... });
Der
click
Handler Callback muss nicht diehugeData
Variable überhaupt. Theoretisch nachprocess(..)
läuft, könnte die riesige DatenstrukturhugeData
Müll gesammelt. Es ist jedoch möglich, dass einige JS Motor wird noch diese riesige Struktur zu halten haben, da dieclick
Funktion eines Verschlusses über den gesamten Umfang hat.Allerdings kann der Block Umfang diese riesige Datenstruktur Müll macht gesammelt.
function process(data) { //... } { // anything declared inside this block can be garbage collected let hugeData = { .. }; process(hugeData); } var btn = document.getElementById("mybutton"); btn.addEventListener( "click", function click(evt){ //.... });
-
let
Schleifenlet
in der Schleife kann Wieder bindet an jede Iteration der Schleife ein, dass sie den Wert aus dem Ende des vorhergehenden Schleifeniteration erneut zuweisen. Betrachten// print '5' 5 times for (var i = 0; i < 5; ++i) { setTimeout(function () { console.log(i); }, 1000); }
Allerdings ersetzen
var
mitlet
// print 1, 2, 3, 4, 5. now for (let i = 0; i < 5; ++i) { setTimeout(function () { console.log(i); }, 1000); }
Da
let
eine neue lexikalische Umgebung mit diesem Namen für ein erstellen) die initialiser Ausdruck b) jede Iteration (previosly die Inkrementausdruck zur Evaluierung), weitere Details sind hier .
Der Hauptunterschied ist der Anwendungsbereich Unterschied, während lassen kann nur innerhalb des Anwendungsbereich verfügbar sein es erklärt, wie in for-Schleife, < strong> var können außerhalb der Schleife beispielsweise zugegriffen werden. Aus der Dokumentation in MDN (Beispiele auch aus MDN):
lassen können Sie Variablen deklarieren, die in ihrem Umfang auf den Block, Anweisung oder ein Ausdruck beschränkt sind, auf denen sie verwendet wird. Dies ist im Gegensatz zu dem var Schlüsselwort, das global eine Variable definiert, oder lokal auf eine gesamte Funktion unabhängig von Blockgültigkeitsbereich.
Variablen deklariert von lassen hat als ihren Umfang den Block, in dem sie definiert sind, sowie in jedem Unterblock enthielt. Auf diese Weise lassen funktioniert ähnlich wie var . Der wesentliche Unterschied besteht darin, dass der Umfang der ein var Variable ist die gesamte einschließende Funktion:
function varTest() {
var x = 1;
if (true) {
var x = 2; // same variable!
console.log(x); // 2
}
console.log(x); // 2
}
function letTest() {
let x = 1;
if (true) {
let x = 2; // different variable
console.log(x); // 2
}
console.log(x); // 1
}`
Auf der obersten Ebene von Programmen und Funktionen, lassen , im Gegensatz zu var , wird keine neue Eigenschaft auf dem globalen Objekt. Zum Beispiel:
var x = 'global';
let y = 'global';
console.log(this.x); // "global"
console.log(this.y); // undefined
Wenn innerhalb eines Blocks verwendet, lassen Sie Grenzen des Anwendungsbereichs der Variable zu diesem Block. Beachten Sie den Unterschied zwischen var , dessen Umfang ist innerhalb der Funktion, wo sie deklariert wird.
var a = 1;
var b = 2;
if (a === 1) {
var a = 11; // the scope is global
let b = 22; // the scope is inside the if-block
console.log(a); // 11
console.log(b); // 22
}
console.log(a); // 11
console.log(b); // 2
Vergessen Sie auch nicht, dass es ECMA6 Feature ist, so ist es noch nicht vollständig unterstützt, so dass es immer besser ist transpiles mit Babel usw ECMA5 ... für weitere Informationen über Besuch babel Website
Hier ist ein Beispiel hinzuzufügen, auf dem, was andere bereits geschrieben. Angenommen, Sie eine Reihe von Funktionen machen wollen, adderFunctions
, wobei jede Funktion eine einzige Nummer Argument verwendet und die Summe des Arguments und der Index der Funktion in der Anordnung. Der Versuch, das adderFunctions
Schlüsselwort var
mit einer Schleife zu erzeugen, indem die Art, wie jemand nicht funktionieren könnte naiv erwarten:
// An array of adder functions.
var adderFunctions = [];
for (var i = 0; i < 1000; i++) {
// We want the function at index i to add the index to its argument.
adderFunctions[i] = function(x) {
// What is i bound to here?
return x + i;
};
}
var add12 = adderFunctions[12];
// Uh oh. The function is bound to i in the outer scope, which is currently 1000.
console.log(add12(8) === 20); // => false
console.log(add12(8) === 1008); // => true
console.log(i); // => 1000
// It gets worse.
i = -8;
console.log(add12(8) === 0); // => true
Das Verfahren, das oben nicht die gewünschte Anordnung von Funktionen erzeugen, weil i
des Oszilloskops über die Iteration des for
Blockes erstreckt, in der jede Funktion erstellt wurde. Stattdessen am Ende der Schleife, die i
in jeder Verschluß der Funktion bezieht sich auf i
Wert am Ende der Schleife (1000) für jede anonyme Funktion in adderFunctions
. Dies ist nicht das, was wir alle wollten: wir jetzt mit genau dem gleichen Verhalten ein Array von 1000 verschiedenen Funktionen im Speicher haben. Und wenn wir anschließend den Wert von i
aktualisieren, wird die Mutation alle adderFunctions
beeinflussen.
Wir können aber versuchen Sie es erneut let
Schlüsselwort:
// Let's try this again.
// NOTE: We're using another ES6 keyword, const, for values that won't
// be reassigned. const and let have similar scoping behavior.
const adderFunctions = [];
for (let i = 0; i < 1000; i++) {
// NOTE: We're using the newer arrow function syntax this time, but
// using the "function(x) { ..." syntax from the previous example
// here would not change the behavior shown.
adderFunctions[i] = x => x + i;
}
const add12 = adderFunctions[12];
// Yay! The behavior is as expected.
console.log(add12(8) === 20); // => true
// i's scope doesn't extend outside the for loop.
console.log(i); // => ReferenceError: i is not defined
Dieses Mal i
ist bei jeder Iteration der Schleife for
Rebound. Jede Funktion hält nun den Wert von i
zum Zeitpunkt der Funktion der Schöpfung und adderFunctions
verhält sich wie erwartet.
Nun Bild Mischen der beiden Verhaltensweisen und Sie werden wahrscheinlich sehen, warum es nicht mit dem älteren let
im selben Skript die neuere const
und var
empfohlen zu mischen. Dadurch führen kann einige spektakuläre verwirrend Code ist.
const doubleAdderFunctions = [];
for (var i = 0; i < 1000; i++) {
const j = i;
doubleAdderFunctions[i] = x => x + i + j;
}
const add18 = doubleAdderFunctions[9];
const add24 = doubleAdderFunctions[12];
// It's not fun debugging situations like this, especially when the
// code is more complex than in this example.
console.log(add18(24) === 42); // => false
console.log(add24(18) === 42); // => false
console.log(add18(24) === add24(18)); // => false
console.log(add18(24) === 2018); // => false
console.log(add24(18) === 2018); // => false
console.log(add18(24) === 1033); // => true
console.log(add24(18) === 1030); // => true
Lassen Sie dies nicht passieren. Verwenden Sie einen Linter.
Hinweis: Dies ist ein Lehrbeispiel sollte das
var
/let
Verhalten in Schleifen und mit Funktionsschließungen demonstrieren, die auch leicht zu verstehen wären. Dies wäre eine schreckliche Art und Weise Zahlen zu addieren. Aber die allgemeine Technik der Daten in anonymer Funktion Schließungen erfassen könnte in der realen Welt in anderen Kontexten auftritt. YMMV.
Der Unterschied liegt in der Umfang der mit jedem deklarierten Variablen.
In der Praxis ergeben sich aus dem unterschiedlichen Geltungsbereich eine Reihe nützlicher Konsequenzen:
let
Variablen sind nur in ihrem sichtbar nächstgelegene Umschließung Block ({ ... }
).let
Variablen können nur in vorkommenden Codezeilen verwendet werden nach Die Variable ist deklariert (obwohl sie werden gehisst!).let
Variablen dürfen nicht durch eine nachfolgende Variable erneut deklariert werdenvar
oderlet
.- Global
let
Variablen werden nicht zum globalen hinzugefügtwindow
Objekt. let
Variablen sind Einfach zu verwenden mit Verschlüssen (sie verursachen nicht Rennbedingungen).
Die Beschränkungen durch let
verringern die Sichtbarkeit der Variablen und erhöhen die Wahrscheinlichkeit, dass unerwartete Namenskollisionen frühzeitig erkannt werden.Dies macht es einfacher, Variablen, einschließlich ihrer Variablen, zu verfolgen und zu begründen Erreichbarkeit(Hilft bei der Rückgewinnung ungenutzten Speichers).
Folglich, let
Es ist weniger wahrscheinlich, dass Variablen Probleme verursachen, wenn sie in großen Programmen verwendet werden oder wenn unabhängig entwickelte Frameworks auf neue und unerwartete Weise kombiniert werden.
var
kann dennoch nützlich sein, wenn Sie sicher sind, dass Sie den Single-Binding-Effekt wünschen, wenn Sie einen Abschluss in einer Schleife verwenden (#5) oder um extern sichtbare globale Variablen in Ihrem Code zu deklarieren (#4).Gebrauch von var
für Exporte können ersetzt werden, wenn export
wandert aus dem Transpilerraum in die Kernsprache.
Beispiele
1.Keine Verwendung außerhalb des nächstgelegenen umschließenden Blocks:Dieser Codeblock löst einen Referenzfehler aus, da er zum zweiten Mal verwendet wird x
tritt außerhalb des Blocks auf, mit dem es deklariert wurde let
:
{
let x = 1;
}
console.log(`x is ${x}`); // ReferenceError during parsing: "x is not defined".
Im Gegensatz dazu das gleiche Beispiel mit var
funktioniert.
2.Keine Verwendung vor der Deklaration:
Dieser Codeblock löst eine aus ReferenceError
bevor der Code ausgeführt werden kann, weil x
wird verwendet, bevor es deklariert wird:
{
x = x + 1; // ReferenceError during parsing: "x is not defined".
let x;
console.log(`x is ${x}`); // Never runs.
}
Im Gegensatz dazu das gleiche Beispiel mit var
analysiert und führt aus, ohne Ausnahmen auszulösen.
3.Keine Neudeklaration:Der folgende Code zeigt, dass eine mit deklarierte Variable let
darf später nicht erneut deklariert werden:
let x = 1;
let x = 2; // SyntaxError: Identifier 'x' has already been declared
4.Globals sind nicht angehängt window
:
var button = "I cause accidents because my name is too common.";
let link = "Though my name is common, I am harder to access from other JS files.";
console.log(link); // OK
console.log(window.link); // undefined (GOOD!)
console.log(window.button); // OK
5.Einfache Anwendung mit Verschlüssen:Mit deklarierte Variablen var
funktionieren nicht gut mit Verschlüssen innerhalb von Schlaufen.Hier ist eine einfache Schleife, die die Wertefolge der Variablen ausgibt i
hat zu verschiedenen Zeitpunkten:
for (let i = 0; i < 5; i++) {
console.log(`i is ${i}`), 125/*ms*/);
}
Im Einzelnen wird Folgendes ausgegeben:
i is 0
i is 1
i is 2
i is 3
i is 4
In JavaScript verwenden wir Variablen häufig zu einem deutlich späteren Zeitpunkt als zum Zeitpunkt ihrer Erstellung.Wenn wir dies demonstrieren, indem wir die Ausgabe mit einem an übergebenen Abschluss verzögern setTimeout
:
for (let i = 0; i < 5; i++) {
setTimeout(_ => console.log(`i is ${i}`), 125/*ms*/);
}
...Die Ausgabe bleibt unverändert, solange wir dabei bleiben let
.Im Gegensatz dazu, wenn wir verwendet hätten var i
stattdessen:
for (var i = 0; i < 5; i++) {
setTimeout(_ => console.log(`i is ${i}`), 125/*ms*/);
}
...Die Schleife gibt unerwartet fünfmal „i ist 5“ aus:
i is 5
i is 5
i is 5
i is 5
i is 5
Auch die beiden folgenden Funktionen zeigen den Unterschied:
function varTest() {
var x = 31;
if (true) {
var x = 71; // Same variable!
console.log(x); // 71
}
console.log(x); // 71
}
function letTest() {
let x = 31;
if (true) {
let x = 71; // Different variable
console.log(x); // 71
}
console.log(x); // 31
}
let
ist interessant, weil es uns so etwas zu tun erlaubt:
(() => {
var count = 0;
for (let i = 0; i < 2; ++i) {
for (let i = 0; i < 2; ++i) {
for (let i = 0; i < 2; ++i) {
console.log(count++);
}
}
}
})();
Welche in Zählergebnisse [0, 7].
Die
(() => {
var count = 0;
for (var i = 0; i < 2; ++i) {
for (var i = 0; i < 2; ++i) {
for (var i = 0; i < 2; ++i) {
console.log(count++);
}
}
}
})();
Nur zählt [0, 1].
Funktion VS Block -umfang:
Der Hauptunterschied zwischen var
und let
ist, dass mit var
deklarierten Variablen sind Funktion scoped . Während bei let
deklarierten Funktionen sind Block scoped . Zum Beispiel:
function testVar () {
if(true) {
var foo = 'foo';
}
console.log(foo);
}
testVar();
// logs 'foo'
function testLet () {
if(true) {
let bar = 'bar';
}
console.log(bar);
}
testLet();
// reference error
// bar is scoped to the block of the if statement
Variablen mit var
:
Wenn die erste Funktion testVar
wird die Variable foo genannt, mit var
erklärt, ist nach wie vor zugänglich außerhalb der if
Aussage. Diese Variable foo
würde zur Verfügung stehen überall im Rahmen der testVar
Funktion .
Variablen mit let
:
Wenn die zweite Funktion testLet
wird die Variable Bar genannt, mit let
erklärt, ist nur in der if
Aussage. Denn mit let
deklarierten Variablen sind Block scoped (wobei ein Block der Code zwischen den geschweiften Klammern ist beispiels if{}
, for{}
, function{}
).
let
Variablen nicht bekommen gehisst:
Ein weiterer Unterschied zwischen var
und let
ist Variablen mit mit let
erklärt nicht gehisst erhalten . Ein Beispiel hierfür ist der beste Weg, um dieses Verhalten zu veranschaulichen:
Variablen mit let
nicht erhalten gehisst:
console.log(letVar);
let letVar = 10;
// referenceError, the variable doesn't get hoisted
Variablen mit var
tun erhalten gehisst:
console.log(varVar);
var varVar = 10;
// logs undefined, the variable gets hoisted
Globale let
nicht window
angebracht bekommt:
Eine Variable mit let
im globalen Bereich erklärt (der Code ist, der nicht in Funktion ist) erhält nicht als Eigenschaft auf dem globalen window
Objekt hinzugefügt. Zum Beispiel (ist dieser Code in globalem Bereich):
var bar = 5;
let foo = 10;
console.log(bar); // logs 5
console.log(foo); // logs 10
console.log(window.bar);
// logs 5, variable added to window object
console.log(window.foo);
// logs undefined, variable not added to window object
Wann sollte über
let
verwendetvar
werden?
Verwenden let
über var
, wann immer Sie können, weil es scoped einfach präziser. Dies reduziert mögliche Namenskonflikte, die auftreten können, wenn sie mit einer großen Anzahl von Variablen zu tun. var
kann verwendet werden, wenn Sie eine globale Variable wollen explizit auf dem window
Objekt sein (immer sorgfältig prüfen, ob dies wirklich notwendig ist).
Es scheint auch, dass, zumindest in Visual Studio 2015, Typoskript 1.5, „var“ mehrere Erklärungen der gleichen Variablennamen in einem Block, und „läßt“ tut erlaubt es nicht.
Das wird kein Compiler-Fehler:
var x = 1;
var x = 2;
Dies wird:
let x = 1;
let x = 2;
var
ist globale Reichweite (Hubwerk-fähig) variabel ist.
let
und const
ist Umfang blockieren.
test.js
{
let l = 'let';
const c = 'const';
var v = 'var';
v2 = 'var 2';
}
console.log(v, this.v);
console.log(v2, this.v2);
console.log(l); // ReferenceError: l is not defined
console.log(c); // ReferenceError: c is not defined
Bei Verwendung let
Das let
Schlüsselwort legt die Variablendeklaration auf den Umfang jegliche Block (allgemein ein { .. }
Paares) es in enthalten ist. Mit anderen Worten, let
implizit jeden Block Rahmen für seine Variablendeklaration hijacks.
let
Variablen können nicht im window
Objekt zugegriffen werden, weil sie nicht global zugegriffen werden.
function a(){
{ // this is the Max Scope for let variable
let x = 12;
}
console.log(x);
}
a(); // Uncaught ReferenceError: x is not defined
Bei Verwendung var
var
und Variablen in ES5 haben Bereiche in Funktionen, die Variablen Bedeutung sind gültig innerhalb der Funktion und nicht außerhalb der Funktion selbst.
var
Variablen kann im window
Objekt zugegriffen werden, weil sie nicht global zugegriffen werden.
function a(){ // this is the Max Scope for var variable
{
var x = 12;
}
console.log(x);
}
a(); // 12
Wenn Sie mehr weiter wissen wollen, lesen Sie unten
eine der bekanntesten Interview Fragen über Umfang auch, wie unten die genaue Verwendung von let
und var
genügen kann;
Bei der Verwendung von let
for (let i = 0; i < 10 ; i++) {
setTimeout(
function a() {
console.log(i); //print 0 to 9, that is literally AWW!!!
},
100 * i);
}
Dies liegt daran, wenn let
verwendet wird, für jede Schleifeniterationslatenzzeit die Variable scoped und hat seine eigene Kopie.
Bei der Verwendung von var
for (var i = 0; i < 10 ; i++) {
setTimeout(
function a() {
console.log(i); //print 10 times 10
},
100 * i);
}
Dies liegt daran, wenn var
verwendet wird, für jede Schleifeniterationslatenzzeit die Variable scoped und hat Kopie geteilt.
Wenn ich die Angaben richtig gelesen dann let
Glück kann auch Funktionen selbst rufenden Privat nur Mitglieder zu simulieren - ein beliebtes Design-Muster, das die Lesbarkeit des Codes ab, erschwert das Debuggen, das keine wirklichen fügt Code-Schutz oder andere Nutzen - außer vielleicht jemand den Wunsch nach Semantik erfüllt, so mehr verwenden. / Rant
var SomeConstructor;
{
let privateScope = {};
SomeConstructor = function SomeConstructor () {
this.someProperty = "foo";
privateScope.hiddenProperty = "bar";
}
SomeConstructor.prototype.showPublic = function () {
console.log(this.someProperty); // foo
}
SomeConstructor.prototype.showPrivate = function () {
console.log(privateScope.hiddenProperty); // bar
}
}
var myInstance = new SomeConstructor();
myInstance.showPublic();
myInstance.showPrivate();
console.log(privateScope.hiddenProperty); // error
Siehe ‚ emulieren private Schnittstellen ‚
Einige Hacks mit let
:
1.
let statistics = [16, 170, 10];
let [age, height, grade] = statistics;
console.log(height)
2.
let x = 120,
y = 12;
[x, y] = [y, x];
console.log(`x: ${x} y: ${y}`);
3.
let node = {
type: "Identifier",
name: "foo"
};
let { type, name, value } = node;
console.log(type); // "Identifier"
console.log(name); // "foo"
console.log(value); // undefined
let node = {
type: "Identifier"
};
let { type: localType, name: localName = "bar" } = node;
console.log(localType); // "Identifier"
console.log(localName); // "bar"
Getter und Setter mit let
:
let jar = {
numberOfCookies: 10,
get cookies() {
return this.numberOfCookies;
},
set cookies(value) {
this.numberOfCookies = value;
}
};
console.log(jar.cookies)
jar.cookies = 7;
console.log(jar.cookies)
vs var lassen. Es ist alles über Anwendungsbereich .
var Variablen global und kann grundsätzlich überall zugegriffen werden kann, während lassen Variablen nicht global sind und nur existieren, bis eine geschlossene Klammer sie tötet.
Sehen Sie mein Beispiel unten, und beachten Sie, wie der Löwe (lassen) Variable wirkt anders in den beiden console.logs; es wird außerhalb des Gültigkeitsbereiches in der 2. console.log.
var cat = "cat";
let dog = "dog";
var animals = () => {
var giraffe = "giraffe";
let lion = "lion";
console.log(cat); //will print 'cat'.
console.log(dog); //will print 'dog', because dog was declared outside this function (like var cat).
console.log(giraffe); //will print 'giraffe'.
console.log(lion); //will print 'lion', as lion is within scope.
}
console.log(giraffe); //will print 'giraffe', as giraffe is a global variable (var).
console.log(lion); //will print UNDEFINED, as lion is a 'let' variable and is now out of scope.
let ist ein Teil von es6. Diese Funktionen werden den Unterschied in der einfachen Weise erklären.
function varTest() {
var x = 1;
if (true) {
var x = 2; // same variable!
console.log(x); // 2
}
console.log(x); // 2
}
function letTest() {
let x = 1;
if (true) {
let x = 2; // different variable
console.log(x); // 2
}
console.log(x); // 1
}
Bisher gab es nur zwei Bereiche in JavaScript, das heißt funktionell und global. Mit 'let
' Schlüsselwort ist Javascript jetzt block-level
Variablen eingeführt.
Um einen vollständigeren Verständnis der 'lassen' Stichwort, ES6: ‚ließ‘ Schlüsselwort Variable in JavaScript erklären helfen
. Jetzt denke ich, es ist besser, Scoping von Variablen auf einen Block von Anweisungen mit let
:
function printnums()
{
// i is not accessible here
for(let i = 0; i <10; i+=)
{
console.log(i);
}
// i is not accessible here
// j is accessible here
for(var j = 0; j <10; j++)
{
console.log(j);
}
// j is accessible here
}
Ich denke, die Menschen beginnen mit hier nach so lassen, dass sie ähnlichen Scoping in JavaScript wie anderen Sprachen, Java, C # haben, etc.
Menschen mit nicht einem klaren Verständnis über in JavaScript Scoping verwendeten den Fehler früher zu machen.
Hissen wird mit let
nicht unterstützt.
Mit diesem Ansatz Fehler in JavaScript werden entfernt zu werden.
Siehe ES6 eingehend :. lassen und konst es besser verstehen
In diesem Artikel klar definiert den Unterschied zwischen var lassen und const
const
ist ein Signal, dass die Kennung nicht neu zugewiesen werden.
let
, ist ein Signal, dass die Variable neu zugewiesen werden kann, wie beispielsweise ein Zähler in einer Schleife oder ein Wert in einem Swap-Algorithmus. Es signalisiert auch dass die Variablen nur in dem Block verwendet werden, es definiert ist in, das ist nicht immer die gesamte enthält Funktion.
var
ist jetzt das schwächste Signal zur Verfügung, wenn Sie eine Variable definieren in JavaScript. Die Variable kann oder auch nicht neu zugewiesen werden, und die Variable kann oder auch nicht für eine ganze Funktion verwendet werden, oder nur für Der Zweck eines Blocks oder einer Schleife.
https: // Medium. com / javascript-Szene / javascript-es6-var-let-or-const-ba58b8dcde75 # .esmkpbg9b
Wie bereits erwähnt:
Der Unterschied ist Scoping.
var
ist scoped zum nächsten Funktion Block undlet
ist scoped auf den nächsten einschließenden Block , die kann als ein Funktionsblock kleiner sein. Beide sind global, wenn außerhalb jeder block.Lets sieht ein Beispiel:
Beispiel 1:
In meinen beiden Beispielen habe ich eine Funktion myfunc
. myfunc
enthält eine variable myvar
bis 10 entspricht.
In meinem ersten Beispiel überprüfe ich, ob myvar
bis 10 (myvar==10
) entspricht. Wenn ja, ich agian eine Variable myvar
erklären (jetzt habe ich zwei myvar Variablen) var
Schlüsselwort und einen neuen Wert (20) zugeordnet werden. In nächster Zeile drucke ich seinen Wert auf meiner Konsole. Nach dem bedingten Block drucke ich wieder den Wert von myvar
auf meiner Konsole. Wenn Sie am Ausgang der myfunc
aussehen, myvar
hat Wert auf 20 gleich
Beispiel 2:
In meinem zweiten Beispiel anstelle var
Schlüsselwort in meinem bedingten Block der Verwendung erkläre ich myvar
let
Schlüsselwort. Nun, wenn ich rufe myfunc
ich zwei verschiedene Ausgänge: myvar=20
und myvar=10
So ist der Unterschied heißt in ihrem Umfang sehr einfach ist.
Werfen Sie einen Blick auf dieses Bild, habe ich ein sehr einfaches Beispiel zur Demonstration der const
und let
Variablen. Wie Sie sehen können, wenn Sie versuchen, const
Variablen zu ändern, werden Sie den Fehler ( Der Versuch, ‚name‘ außer Kraft zu setzen, die " konstant ist), aber einen Blick auf let
Variable nehmen ...
Zuerst erklären wir let age = 33
und später einen anderen Wert age = 34;
zuordnen, die in Ordnung ist, nicht wir Fehler haben, wenn wir let
Variable
Ich denke, die Bedingungen und die meisten Beispiele sind ein wenig überwältigend,
Das Hauptproblem hatte ich persönlich mit dem Unterschied, ist zu verstehen, was ein „Block“ ist.
Irgendwann wurde mir klar, wäre ein Block keine geschweiften Klammern mit Ausnahme IF
Aussage.
ein Öffnungsbügel {
einer Funktion oder Schleife um einen neuen Block zu definieren, definiert etwas mit let
innerhalb es wird nicht nach der Schließbügel }
der gleichen Sache (Funktion oder Schleife) zur Verfügung stehen;
Vor diesem Hintergrund war es leichter zu verstehen:
let msg = "Hello World";
function doWork() { // msg will be available since it was defined above this opening bracket!
let friends = 0;
console.log(msg);
// with VAR though:
for (var iCount2 = 0; iCount2 < 5; iCount2++) {} // iCount2 will be available after this closing bracket!
console.log(iCount2);
for (let iCount1 = 0; iCount1 < 5; iCount1++) {} // iCount1 will not be available behind this closing bracket, it will return undefined
console.log(iCount1);
} // friends will no be available after this closing bracket!
doWork();
console.log(friends);
Als ich gerade versuche, ein tieferes Verständnis von JavaScript erhalten werde ich meine kurze Forschung teilen, die bereits einige der großen Stücke enthält diskutiert sowie einige andere Details in einer anderen Perspektive.
Das Verständnis der Unterschied zwischen var und lassen kann einfacher sein, wenn wir den Unterschied zwischen Funktion und blockieren Umfang .
Lassen Sie uns die folgenden Fälle betrachten:
(function timer() {
for(var i = 0; i <= 5; i++) {
setTimeout(function notime() { console.log(i); }, i * 1000);
}
})();
Stack VariableEnvironment //one VariablEnvironment for timer();
// when the timer is out - the value will be the same value for each call
5. [setTimeout, i] [i=5]
4. [setTimeout, i]
3. [setTimeout, i]
2. [setTimeout, i]
1. [setTimeout, i]
0. [setTimeout, i]
####################
(function timer() {
for (let i = 0; i <= 5; i++) {
setTimeout(function notime() { console.log(i); }, i * 1000);
}
})();
Stack LexicalEnvironment - each iteration has a new lexical environment
5. [setTimeout, i] [i=5]
LexicalEnvironment
4. [setTimeout, i] [i=4]
LexicalEnvironment
3. [setTimeout, i] [i=3]
LexicalEnvironment
2. [setTimeout, i] [i=2]
LexicalEnvironment
1. [setTimeout, i] [i=1]
LexicalEnvironment
0. [setTimeout, i] [i=0]
, wenn timer()
wird aufgerufen, ein ExecutionContext erstellt, die enthalten sowohl die VariableEnvironment und alle LexicalEnvironments zu jeder Iteration entspricht.
Und ein einfacheres Beispiel
Funktionsumfang
function test() {
for(var z = 0; z < 69; z++) {
//todo
}
//z is visible outside the loop
}
Block Scope
function test() {
for(let z = 0; z < 69; z++) {
//todo
}
//z is not defined :(
}
Ich mag diese Schlüsselwörter zu dem Ausführungskontext verknüpfen, weil der Ausführungskontext in all dies wichtig ist. Der Ausführungskontext hat zwei Phasen: eine Erstellungsphase und Ausführungsphase. Darüber hinaus hat jede Ausführung eine Variable Context Umwelt und äußeren Umgebung (ihre Lexical Umgebung).
Während der Entstehungsphase eines Ausführungskontextes, var, lassen und const speichert noch seine Variable im Speicher mit einem nicht definierten Wert in der Variable Umwelt des Kontextes gegeben Ausführung. Der Unterschied liegt in der Ausführungsphase. Wenn Sie Referenz eine Variable definiert mit var verwenden, bevor es einen Wert zugewiesen wird, wird es nur nicht definiert sein. Keine Ausnahme wird angehoben.
Sie können jedoch nicht die Variable mit let oder const deklariert verweisen, bis sie deklariert wird. Wenn Sie versuchen, es zu benutzen, bevor es deklariert wird, dann wird eine Ausnahme während der Ausführungsphase des Ausführungskontextes erhöht werden. Nun werden noch die Variablen im Speicher sein, mit freundlicher Genehmigung von der Erstellungsphase des Ausführungskontextes, aber der Motor wird nicht zulassen, dass Sie es verwenden:
function a(){
b;
let b;
}
a();
> Uncaught ReferenceError: b is not defined
Mit einer Variablen mit var definiert, wenn der Motor nicht die Variable in der aktuellen Ausführungskontext der Variable Environment finden können, dann wird es den Umfang Kette (die äußere Umwelt) und prüfen Sie die äußere Umgebung der Variable Environment für die Variable steigen. Wenn es nicht dort finden kann, wird es auch weiterhin die Scope-Kette zu suchen. Dies ist nicht der Fall mit let und konst.
Das zweite Merkmal von let ist es Block Umfang einführt. Die Blöcke werden von geschweiften Klammern definiert. Beispiele hierfür sind Funktionsbausteine, wenn Blöcke, für die Blöcke, usw. Wenn Sie eine Variable mit let innerhalb eines Blocks deklarieren, die Variable innerhalb des Blocks nur zur Verfügung steht. In der Tat, jedes Mal wird der Block ausgeführt werden, wie zum Beispiel innerhalb eines for-Schleife, wird es eine neue Variable im Speicher erstellen.
ES6 führt auch das Schlüsselwort const Variablen zu deklarieren. const wird auch Block scoped. Der Unterschied zwischen let und const ist, dass konstante Variablen deklariert werden müssen einen Initialisierer verwendet wird, oder es wird ein Fehler generiert.
Und schließlich, wenn es um den Ausführungskontext kommt, Variablen mit var definiert wird das ‚dieses‘ Objekt angebracht werden. Im Kontext globalen Ausführung, das wird das Fensterobjekt in Browsern. Dies ist nicht der Fall für vermietete oder konst.