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?

War es hilfreich?

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?

, 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:

 Auflagetisch


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 wie var. Der Hauptunterschied besteht darin, dass der Umfang eines var 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):
eingeben Bild Beschreibung hier

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 Hoisting

    let wird nicht hissen , um den gesamten Umfang des Blockes sie erscheinen in. Im Gegensatz dazu var 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 und let sind gehisst .

  • Garbage Collection

    Blockumfang let nützlich ist, bezieht sich auf Verschlüsse und Garbage Collection Speicher zurückzufordern. Betrachten

    function process(data) {
        //...
    }
    
    var hugeData = { .. };
    
    process(hugeData);
    
    var btn = document.getElementById("mybutton");
    btn.addEventListener( "click", function click(evt){
        //....
    });
    

    Der click Handler Callback muss nicht die hugeData Variable überhaupt. Theoretisch nach process(..) läuft, könnte die riesige Datenstruktur hugeData Müll gesammelt. Es ist jedoch möglich, dass einige JS Motor wird noch diese riesige Struktur zu halten haben, da die click 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 Schleifen

    let 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 mit let

    // 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:

  1. let Variablen sind nur in ihrem sichtbar nächstgelegene Umschließung Block ({ ... }).
  2. let Variablen können nur in vorkommenden Codezeilen verwendet werden nach Die Variable ist deklariert (obwohl sie werden gehisst!).
  3. let Variablen dürfen nicht durch eine nachfolgende Variable erneut deklariert werden var oder let.
  4. Global let Variablen werden nicht zum globalen hinzugefügt window Objekt.
  5. 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 verwendet var 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 und let 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

zu ändern versuchen

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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top