Frage Was ist der Unterschied zwischen der Verwendung von "let" und "var", um eine Variable in JavaScript zu deklarieren?


ECMAScript 6 eingeführt das let Erklärung. Ich habe es als eine "lokale" Variable beschrieben, aber ich bin mir immer noch nicht ganz sicher, wie es sich anders verhält als das var Stichwort.

Was sind die Unterschiede? Wann sollte let über verwendet werden var?


3238
2018-04-17 20:09


Ursprung


Antworten:


Der Unterschied ist das Scoping. var ist auf den nächsten Funktionsblock und let ist auf den nächsten Bereich beschränkt umschließend Block, der kleiner als ein Funktionsblock sein kann. Beide sind global, wenn sie außerhalb eines Blocks liegen.

Auch Variablen, die mit deklariert wurden let sind nicht zugänglich, bevor sie in ihrem umschließenden Block deklariert sind. Wie in der Demo gezeigt, löst dies eine ReferenceError-Ausnahme aus.

Demo: 

var html = '';

write('#### global ####\n');
write('globalVar: ' + globalVar); //undefined, but visible

try {
  write('globalLet: ' + globalLet); //undefined, *not* visible
} catch (exception) {
  write('globalLet: exception');
}

write('\nset variables');

var globalVar = 'globalVar';
let globalLet = 'globalLet';

write('\nglobalVar: ' + globalVar);
write('globalLet: ' + globalLet);

function functionScoped() {
  write('\n#### function ####');
  write('\nfunctionVar: ' + functionVar); //undefined, but visible

  try {
    write('functionLet: ' + functionLet); //undefined, *not* visible
  } catch (exception) {
    write('functionLet: exception');
  }

  write('\nset variables');

  var functionVar = 'functionVar';
  let functionLet = 'functionLet';

  write('\nfunctionVar: ' + functionVar);
  write('functionLet: ' + functionLet);
}

function blockScoped() {
  write('\n#### block ####');
  write('\nblockVar: ' + blockVar); //undefined, but visible

  try {
    write('blockLet: ' + blockLet); //undefined, *not* visible
  } catch (exception) {
    write('blockLet: exception');
  }

  for (var blockVar = 'blockVar', blockIndex = 0; blockIndex < 1; blockIndex++) {
    write('\nblockVar: ' + blockVar); // visible here and whole function
  };

  for (let blockLet = 'blockLet', letIndex = 0; letIndex < 1; letIndex++) {
    write('blockLet: ' + blockLet); // visible only here
  };

  write('\nblockVar: ' + blockVar);

  try {
    write('blockLet: ' + blockLet); //undefined, *not* visible
  } catch (exception) {
    write('blockLet: exception');
  }
}

function write(line) {
  html += (line ? line : '') + '<br />';
}

functionScoped();
blockScoped();

document.getElementById('results').innerHTML = html;
<pre id="results"></pre>

Global:

Sie sind sehr ähnlich, wenn sie außerhalb eines Funktionsblocks verwendet werden.

let me = 'go';  // globally scoped
var i = 'able'; // globally scoped

Globale Variablen, die mit definiert sind let wird nicht als Eigenschaften im globalen Bereich hinzugefügt window Objekt wie die mit definiert var.

console.log(window.me); // undefined
console.log(window.i); // 'able'

Funktion:

Sie sind identisch, wenn sie in einem Funktionsblock verwendet werden.

function ingWithinEstablishedParameters() {
    let terOfRecommendation = 'awesome worker!'; //function block scoped
    var sityCheerleading = 'go!'; //function block scoped
}

Block:

Hier ist der Unterschied. let ist nur sichtbar in der for() Schleife und var ist für die gesamte Funktion sichtbar.

function allyIlliterate() {
    //tuce is *not* visible out here

    for( let tuce = 0; tuce < 5; tuce++ ) {
        //tuce is only visible in here (and in the for() parentheses)
        //and there is a separate tuce variable for each iteration of the loop
    }

    //tuce is *not* visible out here
}

function byE40() {
    //nish *is* visible out here

    for( var nish = 0; nish < 5; nish++ ) {
        //nish is visible to the whole function
    }

    //nish *is* visible out here
}

Redeklaerung:

Unter der Annahme eines strikten Modus var Sie können dieselbe Variable im selben Bereich erneut deklarieren. Andererseits, let wird nicht:

'use strict';
let me = 'foo';
let me = 'bar'; // SyntaxError: Identifier 'me' has already been declared
'use strict';
var me = 'foo';
var me = 'bar'; // No problem, `me` is replaced.

4549
2018-05-27 10:16



let kann auch verwendet werden, um Probleme mit Verschlüssen zu vermeiden. Es bindet einen neuen Wert, anstatt eine alte Referenz beizubehalten, wie in den folgenden Beispielen gezeigt.

DEMO

for(var i = 1; i < 6; i++) {
  document.getElementById('my-element' + i)
    .addEventListener('click', function() { alert(i) })
}

Der obige Code demonstriert ein klassisches JavaScript-Schließungsproblem. Hinweis auf die i Die Variable wird in der Click-Handler-Schließung gespeichert und nicht im tatsächlichen Wert von i.

Jeder einzelne Click-Handler verweist auf dasselbe Objekt, da es nur ein Counter-Objekt gibt, das 6 enthält, sodass Sie bei jedem Klick sechs erhalten.

Eine allgemeine Problemumgehung besteht darin, diese in eine anonyme Funktion einzubinden und zu übergeben i als Argument. Solche Probleme können jetzt auch durch Verwendung vermieden werden let stattdessen var wie im folgenden Code gezeigt.

DEMO (Getestet in Chrome und Firefox 50)

'use strict';

for(let i = 1; i < 6; i++) {
  document.getElementById('my-element' + i)
    .addEventListener('click', function() { alert(i) })
}

450
2018-04-17 20:11



Hier ist ein Erklärung der let Stichwort mit einigen Beispielen.

lassen Sie sich sehr ähnlich wie var. Der Hauptunterschied besteht darin, dass der Bereich einer var-Variablen die gesamte umschließende Funktion ist

Dieser Tisch auf Wikipedia zeigt, welche Browser Javascript 1.7 unterstützen.

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


129
2018-02-23 18:35



Was ist der Unterschied zwischen let und var?

  • Eine Variable, die mit a definiert wird var Aussage ist überall bekannt die Funktion Es ist ab dem Start der Funktion definiert. (*)
  • Eine Variable, die mit a definiert wird let Aussage ist nur in bekannt der Block es ist ab dem Zeitpunkt der Definition definiert. (**)

Beachten Sie den folgenden Code, um den Unterschied zu verstehen:

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

Beachten Sie außerdem, dass Blockbereichsvariablen nicht bekannt sind, bevor sie deklariert werden, da sie nicht gehisst sind. Es ist Ihnen auch nicht erlaubt, dieselbe Block-Bereichsvariable innerhalb desselben Blocks neu zu deklarieren. Dies macht Block-Scoped-Variablen weniger fehleranfällig als Global- oder Funktions-Scoped-Variablen, die gehisst werden und die bei mehreren Deklarationen keine Fehler erzeugen.


Ist es sicher zu benutzen? let heute?

Einige Leute würden argumentieren, dass wir in Zukunft nur noch let-Anweisungen verwenden werden und dass var-Anweisungen veraltet werden. JavaScript-Guru Kyle Simpson schrieb ein sehr ausführlicher Artikel darüber, warum das nicht der Fall ist.

Heute ist das jedoch definitiv nicht der Fall. Tatsächlich müssen wir uns tatsächlich fragen, ob es sicher ist, das zu verwenden let Erklärung. Die Antwort auf diese Frage hängt von Ihrer Umgebung ab:

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

  • Wenn Sie clientseitigen JavaScript-Code schreiben und einen transpiler (wie Traceur), können Sie sicher das verwenden let Allerdings ist Ihr Code in Bezug auf die Leistung wahrscheinlich alles andere als optimal.

  • Wenn Sie clientseitigen JavaScript-Code schreiben und keinen transpiler verwenden, müssen Sie die Browserunterstützung in Betracht ziehen.

Heute, 8. Juni 2018, gibt es immer noch einige Browser, die dies nicht unterstützen let!

enter image description here


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

Für einen aktuellen Überblick darüber, welche Browser den Browser unterstützen let Aussage zum Zeitpunkt der Lektüre dieser Antwort, siehe Dies Can I Use Seite.


(*) Global und funktional beschränkte Variablen können initialisiert und verwendet werden, bevor sie deklariert werden, weil JavaScript Variablen sind gehisst. Dies bedeutet, dass Deklarationen immer ganz oben stehen.

(**) Block-Bereichsvariablen werden nicht gehisst


115
2018-06-02 20:59



Die akzeptierte Antwort fehlt ein Punkt:

{
  let a = 123;
};

console.log(a); // ReferenceError: a is not defined

98
2018-04-17 21:38



Es gibt einige subtile Unterschiede - let Scoping verhält sich mehr wie das variable Scoping in mehr oder weniger anderen Sprachen.

z.B. Es erstreckt sich auf den umschließenden Block. Sie existieren nicht, bevor sie deklariert sind usw.

Es ist jedoch erwähnenswert let ist nur ein Teil von neueren Javascript-Implementierungen und hat unterschiedliche Grade von Browser-Unterstützung.


40
2018-03-06 10:41



Hier ist ein Beispiel für den Unterschied zwischen den beiden (Unterstützung für Chrome wurde gerade gestartet): enter image description here

Wie Sie sehen können var j Die Variable hat immer noch einen Wert außerhalb des Bereichs der for-Schleife (Blockbereich), aber die let i Die Variable ist außerhalb des For-Schleifenbereichs 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);


39
2017-11-23 22:52



let

Bereich blockieren

Variablen, die mit der Funktion let Schlüsselwort sind Block-Bereich, was bedeutet, dass sie nur in der Block in denen sie erklärt wurden.

Auf der obersten Ebene (außerhalb einer Funktion)

Auf der obersten Ebene werden Variablen deklariert mit let Erstellen Sie keine Eigenschaften für das globale Objekt.

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

In einem Block

Variablen, die mit deklariert wurden let Innerhalb eines Blocks kann außerhalb dieses Blocks nicht 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

In einer Schleife

Variablen deklariert 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.

Loops mit Verschlüssen

Wenn du benutzt let Anstatt von var In einer Schleife erhält man mit jeder Iteration eine neue Variable. Das bedeutet, dass Sie einen Verschluss 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);
}

Temporale Totzone

Durch die zeitliche TotzoneVariablen, die mit deklariert wurden let auf sie kann nicht zugegriffen werden, bevor sie deklariert sind. Der Versuch, dies zu tun, löst einen Fehler aus.

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

Keine erneute Deklaration

Sie können die gleiche Variable nicht mehrmals mit deklarieren let. Sie können eine Variable auch nicht mit deklarieren let mit dem gleichen Bezeichner wie eine andere Variable, die mit deklariert wurde 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-s ist block-scoped und hat TDZ. Es gibt jedoch zwei Dinge, die sich unterscheiden.

Keine Neuzuweisung

Variable deklariert mit const kann nicht neu zugewiesen werden.

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

Beachten Sie, dass dies 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 möchten, sollten Sie es verwenden Object.freeze().

Initialisierer ist erforderlich

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

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

37
2018-01-17 15:11