6215 Stimmen

Was ist der Unterschied zwischen der Verwendung von "let" und "var"?

ECMAScript 6 eingeführt die let Anweisung .

Ich habe gehört, dass man es als eine local Variable, aber ich bin mir immer noch nicht ganz sicher, warum sie sich anders verhält als die var Stichwort.

Was sind die Unterschiede? Wann sollte let verwendet werden anstelle von var ?

133 Stimmen

ECMAScript ist der Standard und let ist enthalten in der Entwurf der 6. Auflage und wird höchstwahrscheinlich in der endgültigen Spezifikation enthalten sein.

12 Stimmen

Véase kangax.github.io/es5-compat-table/es6 für eine aktuelle Unterstützungsmatrix der ES6-Funktionen (einschließlich let). Zum Zeitpunkt der Erstellung dieses Artikels unterstützen Firefox, Chrome und IE11 diese Funktion (obwohl ich glaube, dass die Implementierung von FF nicht ganz Standard ist).

37 Stimmen

Die längste Zeit wusste ich nicht, dass Variablen in einer for-Schleife auf die Funktion, in die sie eingeschlossen war, skaliert wurden. Ich erinnere mich, dass ich dies zum ersten Mal herausfand und dachte, es sei sehr dumm. Jetzt weiß ich allerdings, wie die beiden aus unterschiedlichen Gründen verwendet werden können und dass man in manchen Fällen eine Variable in einer for-Schleife verwenden möchte, ohne dass sie auf den Block skaliert ist.

8145voto

ThinkingStiff Punkte 63624

Regeln für das Scoping

Der Hauptunterschied besteht in den Regeln für den Geltungsbereich. Variablen, die durch var Schlüsselwort auf den unmittelbaren Funktionsrumpf (daher der Funktionsumfang) beschränkt, während let Variablen sind auf den unmittelbaren einschließen. Block, bezeichnet mit { } (daher der Blockumfang).

function run() {
  var foo = "Foo";
  let bar = "Bar";

  console.log(foo, bar); // Foo Bar

  {
    var moo = "Mooo"
    let baz = "Bazz";
    console.log(moo, baz); // Mooo Bazz
  }

  console.log(moo); // Mooo
  console.log(baz); // ReferenceError
}

run();

Der Grund dafür let Schlüsselwort in die Sprache eingeführt wurde, ist Funktionsumfang verwirrend und war eine der Hauptquellen von Fehlern in JavaScript.

Schauen Sie sich dieses Beispiel aus eine weitere Stack Overflow-Frage :

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 wurde jedes Mal auf die Konsole ausgegeben, wenn funcs[j](); aufgerufen wurde, da anonyme Funktionen an dieselbe Variable gebunden waren.

Die Leute mussten sofort aufgerufene Funktionen erstellen, um korrekte Werte aus den Schleifen zu erfassen, aber das war auch haarig.

Heben

Während Variablen, die mit var Stichwort sind hochgezogen. (initialisiert mit undefined bevor der Code ausgeführt wird), was bedeutet, dass sie in ihrem umschließenden Bereich zugänglich sind, noch bevor sie deklariert werden:

function run() {
  console.log(foo); // undefined
  var foo = "Foo";
  console.log(foo); // Foo
}

run();

let Variablen werden nicht initialisiert, bis ihre Definition ausgewertet wird. Der Zugriff auf sie vor der Initialisierung führt zu einem ReferenceError . Die Variable befindet sich vom Beginn des Blocks bis zur Verarbeitung der Initialisierung im "zeitlichen Totbereich".

function checkHoisting() {
  console.log(foo); // ReferenceError
  let foo = "Foo";
  console.log(foo); // Foo
}

checkHoisting();

Erstellen einer globalen Objekteigenschaft

Auf der obersten Ebene, let im Gegensatz zu var wird keine Eigenschaft auf dem globalen Objekt erstellt:

var foo = "Foo";  // globally scoped
let bar = "Bar"; // not allowed to be globally scoped

console.log(window.foo); // Foo
console.log(window.bar); // undefined

Neuanmeldung

Im strengen Modus, var ermöglicht es Ihnen, dieselbe Variable im selben Bereich erneut zu deklarieren, während let löst einen SyntaxFehler aus.

'use strict';
var foo = "foo1";
var foo = "foo2"; // No problem, 'foo1' is replaced with 'foo2'.

let bar = "bar1"; 
let bar = "bar2"; // SyntaxError: Identifier 'bar' has already been declared

73 Stimmen

Denken Sie daran, dass Sie jederzeit einen Block erstellen können. function() { code;{ let inBlock = 5; } code; };

254 Stimmen

Dienen let-Anweisungen also nur dazu, Speicher freizugeben, wenn er in einem bestimmten Block nicht benötigt wird?

297 Stimmen

@NoBugs, Ja, und es wird empfohlen, dass Variablen nur dort vorhanden sind, wo sie benötigt werden.

821voto

Gurpreet Singh Punkte 20089

let kann auch verwendet werden, um Probleme mit Verschlüssen zu vermeiden. Es bindet einen neuen Wert, anstatt eine alte Referenz zu behalten, wie in den folgenden 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>
<p>Clicking on each number will log to console:</p> 
<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>

Der obige Code demonstriert ein klassisches JavaScript-Closure-Problem. Verweis auf die i Variable in der Click-Handler-Schließung gespeichert wird und nicht der tatsächliche Wert von i .

Jeder einzelne Klick-Handler verweist auf dasselbe Objekt, da es nur ein Zähler-Objekt gibt, das 6 Zähler enthält, so dass Sie bei jedem Klick sechs Zähler erhalten.

Eine allgemeine Abhilfe besteht darin, dies in eine anonyme Funktion zu verpacken und die i als Argument. Solche Probleme können jetzt auch vermieden werden, indem man let stattdessen var wie im nachstehenden Code gezeigt.

(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>
<p>Clicking on each number will log to console:</p> 
<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>

79 Stimmen

Das ist wirklich cool. Ich würde erwarten, dass "i" außerhalb des Schleifenkörpers innerhalb von Klammern definiert wird und KEINE "Schließung" um "i" herum bildet, aber Ihr Beispiel beweist das Gegenteil. Ich denke, dass es von der Syntax her ein wenig verwirrend ist, aber dieses Szenario ist so häufig, dass es Sinn macht, es auf diese Weise zu unterstützen. Vielen Dank für diesen Hinweis.

12 Stimmen

IE 11 unterstützt let aber es meldet "6" für alle Tasten. Haben Sie eine Quelle, die sagt, wie let sich verhalten soll?

13 Stimmen

Es sieht so aus, als ob Ihre Antwort das richtige Verhalten ist: developer.mozilla.org/de-US/docs/Web/JavaScript/Reference/

333voto

John Slegers Punkte 41127

Was ist der Unterschied zwischen let y var ?

  • Eine Variable, die mit einer var Aussage ist überall bekannt die Funktion in dem sie definiert ist, vom Beginn der Funktion an. (*)
  • Eine Variable, die mit einer let Anweisung ist nur bekannt in der Block in dem er definiert ist, und zwar von dem Moment an, in dem er definiert wird. (**)

Um den Unterschied zu verstehen, betrachten Sie den folgenden Code:

// 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 ist nur in der ersten for-Schleife bekannt, nicht aber davor und danach. Dennoch ist unsere Variable i ist in der gesamten Funktion bekannt.

Berücksichtigen Sie auch, dass blockscoped Variablen nicht bekannt sind, bevor sie deklariert werden, da sie nicht gehostet werden. Es ist auch nicht erlaubt, dieselbe blockscoped Variable innerhalb desselben Blocks erneut zu deklarieren. Dadurch sind blockscoped-Variablen weniger fehleranfällig als global oder funktional scoped-Variablen, die hoisted sind und bei Mehrfachdeklarationen keine Fehler verursachen.


Ist es sicher zu verwenden let heute?

Einige Leute würden behaupten, dass wir in Zukunft NUR noch let-Anweisungen verwenden werden und dass var-Anweisungen überflüssig werden. JavaScript-Guru Kyle Simpson schrieb einen sehr ausführlichen Artikel darüber, warum er glaubt, dass dies nicht der Fall sein wird .

Heute ist das jedoch definitiv nicht mehr der Fall. Vielmehr müssen wir uns fragen, ob es sicher ist, die let Erklärung. Die Antwort auf diese Frage hängt von Ihrem Umfeld ab:

  • Wenn Sie serverseitigen JavaScript-Code schreiben ( Node.js ), können Sie sicher die let Erklärung.

  • Wenn Sie clientseitigen JavaScript-Code schreiben und einen browserbasierten Transpiler verwenden (wie Traceur o babel-standalone ), können Sie sicher die let Anweisung ist Ihr Code jedoch wahrscheinlich alles andere als optimal in Bezug auf die Leistung.

  • Wenn Sie clientseitigen JavaScript-Code schreiben und einen Node-basierten Transpiler (wie den Traceur-Shell-Skript o Babel ), können Sie sicher die let Erklärung. Und da Ihr Browser nur den umgesetzten Code kennt, dürften sich die Leistungseinbußen in Grenzen halten.

  • Wenn Sie clientseitigen JavaScript-Code schreiben und keinen Transpiler verwenden, müssen Sie die Browserunterstützung berücksichtigen.

    Es gibt immer noch einige Browser, die Folgendes nicht unterstützen let überhaupt nicht:

enter image description here


So behalten Sie den Überblick über die Browserunterstützung

Für einen aktuellen Überblick darüber, welche Browser die let Aussage zum Zeitpunkt des Lesens dieser Antwort, siehe este Can I Use Seite .


(*) Globale und funktional skalierte Variablen können initialisiert und verwendet werden, bevor sie deklariert werden, da JavaScript-Variablen hochgezogen. . Das bedeutet, dass Deklarationen immer ganz oben im Geltungsbereich stehen.

(**) Blockspezifische Variablen werden nicht hochgezogen

23 Stimmen

Zur Antwort v4: i IST überall im Funktionsblock bekannt! Er beginnt als undefined (wegen des Aufzugs), bis Sie einen Wert zuweisen! ps: let wird ebenfalls hochgezogen (an die Spitze des Blocks, der ihn enthält), gibt aber eine ReferenceError wenn im Block vor der ersten Zuweisung darauf verwiesen wird. (ps2: Ich bin ein Verfechter des Semikolons, aber man braucht wirklich kein Semikolon nach einem Block). Davon abgesehen, danke für den Realitäts-Check bezüglich der Unterstützung!

0 Stimmen

@GitaarLAB : Laut dem Mozilla-Entwickler-Netzwerk : "In ECMAScript 2015 unterliegen Let-Bindungen nicht dem Variable Hoisting, was bedeutet, dass Let-Deklarationen nicht an den Anfang des aktuellen Ausführungskontexts verschoben werden." - Wie auch immer, ich habe einige Verbesserungen an meiner Antwort vorgenommen, die den Unterschied im Hoisting-Verhalten zwischen let y var !

2 Stimmen

Ihre Antwort hat sich sehr verbessert (ich habe sie gründlich überprüft). Beachten Sie, dass derselbe Link, auf den Sie in Ihrem Kommentar verweisen, auch besagt: "Die (let) Variable befindet sich in einer "zeitlich toten Zone" vom Beginn des Blocks bis die Initialisierung abgeschlossen ist." Das bedeutet, dass der "Bezeichner" (der Text-String, der "reserviert" ist, um auf "etwas" zu zeigen) ist bereits in dem betreffenden Bereich reserviert, da es sonst Teil des Bereichs Root/Host/Fenster werden würde. Für mich persönlich bedeutet "hoisting" nichts anderes als die Reservierung/Verknüpfung von deklarierten "Identifikatoren" mit ihrem jeweiligen Bereich; ausgenommen ihre Initialisierung/Zuweisung/Änderbarkeit!

184voto

Ben S Punkte 66945

Hier ist ein Erläuterung der let Stichwort mit einigen Beispielen.

let funktioniert sehr ähnlich wie var . Der Hauptunterschied besteht darin, dass der Anwendungsbereich einer var Variable ist die gesamte umschließende Funktion

Diese Tabelle auf Wikipedia zeigt, welche Browser Javascript 1.7 unterstützen.

Beachten Sie, dass nur Mozilla- und Chrome-Browser diese Funktion unterstützen. IE, Safari und möglicherweise andere nicht.

7 Stimmen

Der Schlüsseltext aus dem verlinkten Dokument scheint zu sein: "let funktioniert ähnlich wie var. Der Hauptunterschied besteht darin, dass der Geltungsbereich einer var-Variablen die gesamte umschließende Funktion ist".

59 Stimmen

@olliej, eigentlich ist Mozilla dem Spiel einfach voraus. Siehe Seite 19 von ecma-international.org/veroeffentlichungen/files/ECMA-ST/Ecma-262.pdf

1 Stimmen

@TylerCrompton das ist genau die Wortgruppe, die seit Jahren reserviert ist. Als Mozilla let hinzufügte, war es eine reine Mozilla-Erweiterung ohne zugehörige Spezifikation. ES6 sollte das Verhalten für let-Anweisungen definieren, aber das kam erst, nachdem Mozilla die Syntax eingeführt hatte. Denken Sie daran, dass moz auch E4X hat, das völlig tot ist und nur von moz stammt.

151voto

Michał Perłakowski Punkte 79585

let

Blockumfang

Variablen, die mit der Option let Schlüsselwortes sind block-scoped, d.h. sie sind nur in der Block in dem sie angemeldet wurden.

Auf der obersten Ebene (außerhalb einer Funktion)

Auf der obersten Ebene werden Variablen, die mit let keine Eigenschaften für das globale 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 Geltungsbereich 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

Variablen, die mit let innerhalb eines Blocks können nicht außerhalb dieses Blocks aufgerufen 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, die mit let in Schleifen können nur innerhalb dieser Schleife 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.

Schleifen mit Verschlüssen

Wenn Sie let anstelle von var in einer Schleife, bei jeder Iteration erhalten Sie eine neue Variable. Das bedeutet, dass Sie eine Schließung innerhalb einer Schleife sicher 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);
}

Zeitlich tote Zone

Wegen der die zeitlich tote Zone Variablen, die mit let können nicht aufgerufen werden, bevor sie deklariert sind. Der Versuch, dies zu tun, führt zu einem Fehler.

console.log(noTDZ); // undefined
var noTDZ = 43;
console.log(hasTDZ); // ReferenceError: hasTDZ is not defined
let hasTDZ = 42;

Keine Neuanmeldung

Sie können dieselbe Variable nicht mehrfach deklarieren, indem Sie let . Sie können eine Variable auch nicht deklarieren, indem Sie let mit demselben Bezeichner wie eine andere Variable, die mit var .

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 sehr ähnlich zu let -Es ist blockiert und hat TDZ. Es gibt jedoch zwei Dinge, die anders sind.

Keine Neuzuteilung

Variable, die mit const kann nicht neu zugewiesen werden.

const a = 42;
a = 43; // TypeError: Assignment to constant variable.

Dies bedeutet jedoch nicht, dass der Wert unveränderlich ist. Seine Eigenschaften können immer 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() .

const obj = Object.freeze({a: 40});
obj.a = 42;
console.log(obj.a); // 40
console.log(obj.b); // undefined

Initialisierung ist erforderlich

Sie müssen immer einen Wert angeben, wenn Sie eine Variable mit const .

const a; // SyntaxError: Missing initializer in const declaration

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X