Domanda Qual è la differenza tra l'uso di "let" e "var" per dichiarare una variabile in JavaScript?


ECMAScript 6 introdotto il let dichiarazione. L'ho sentito descritto come una variabile "locale", ma non sono ancora abbastanza sicuro di come si comporta in modo diverso rispetto al var parola chiave.

Quali sono le differenze? Quando dovrebbe let essere usato finita var?


3237
2018-04-17 20:09


origine


risposte:


La differenza è l'ambito. var è circoscritto al blocco funzione più vicino e let è circoscritto al più vicino racchiude blocco, che può essere più piccolo di un blocco funzione. Entrambi sono globali se fuori da qualsiasi blocco.

Inoltre, le variabili dichiarate con let non sono accessibili prima che siano dichiarati nel loro blocco di chiusura. Come visto nella demo, questo genererà un'eccezione ReferenceError.

dimostrazione: 

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>

Globale:

Sono molto simili se usati in questo modo al di fuori di un blocco funzione.

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

Tuttavia, le variabili globali definite con let non saranno aggiunti come proprietà sul globale window oggetto come quelli definiti con var.

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

Funzione:

Sono identici se usati in questo modo in un blocco funzione.

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

Bloccare:

Ecco la differenza. let è visibile solo nel for() ciclo e var è visibile all'intera funzione.

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
}

ridichiarazione:

Supponendo la modalità rigorosa, var ti permetterà di ri-dichiarare la stessa variabile nello stesso ambito. D'altra parte, let non:

'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.

4546
2018-05-27 10:16



let può anche essere usato per evitare problemi con chiusure. Lega valore fresco piuttosto che mantenere un vecchio riferimento come mostrato negli esempi di seguito.

DEMO

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

Il codice sopra mostra un classico problema di chiusura di JavaScript. Riferimento al i la variabile viene archiviata nella chiusura del gestore di clic, anziché il valore effettivo di i.

Ogni singolo click handler si riferirà allo stesso oggetto perché c'è un solo oggetto contatore che ne contiene 6, quindi ottieni sei per ogni clic.

La soluzione generale consiste nel racchiuderlo in una funzione anonima e passare i come argomento. Tali problemi possono anche essere evitati ora usando let anziché var come mostrato nel codice qui sotto.

DEMO (Testato su Chrome e 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



Ecco un spiegazione del let parola chiave con alcuni esempi

lascia che funzioni molto come var. La differenza principale è che l'ambito di una variabile var è l'intera funzione di chiusura

Questo tavolo su Wikipedia mostra quali browser supportano Javascript 1.7.

Nota che solo i browser Mozilla e Chrome lo supportano. IE, Safari e potenzialmente altri no.


129
2018-02-23 18:35



Qual è la differenza tra let e var?

  • Una variabile definita usando a var la dichiarazione è nota in tutto la funzione è definito in, dall'inizio della funzione. (*)
  • Una variabile definita usando a let la dichiarazione è conosciuta solo in il blocco è definito in, dal momento in cui è definito in poi. (**)

Per capire la differenza, considera il seguente codice:

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

Qui, possiamo vedere che la nostra variabile j è noto solo nel primo ciclo for, ma non prima e dopo. Eppure, la nostra variabile i è noto nell'intera funzione.

Inoltre, considera che le variabili con scope a blocchi non sono note prima di essere dichiarate perché non vengono issate. Inoltre, non è consentito ridichiarare la stessa variabile nell'ambito dello stesso blocco. Questo rende le variabili con scope limitato meno soggette a errori rispetto a variabili globalmente o funzionalmente con scope, che vengono issate e che non producono errori nel caso di più dichiarazioni.


È sicuro da usare let oggi?

Alcuni sostengono che in futuro utilizzeremo SOLO le dichiarazioni let e che le istruzioni var diventeranno obsolete. Guru di JavaScript Kyle Simpson ha scritto un articolo molto elaborato sul perché non è così.

Oggi, tuttavia, questo non è assolutamente il caso. In realtà, dobbiamo effettivamente chiederci se è sicuro usare il let dichiarazione. La risposta a questa domanda dipende dal tuo ambiente:

  • Se stai scrivendo codice JavaScript lato server (Node.js), puoi tranquillamente usare il let dichiarazione.

  • Se stai scrivendo codice JavaScript lato client e usi un transpiler (come traceur), puoi tranquillamente usare il let affermazione, tuttavia il tuo codice è probabilmente tutt'altro che ottimale per quanto riguarda le prestazioni.

  • Se stai scrivendo codice JavaScript lato client e non usi un transpiler, devi considerare il supporto del browser.

Oggi, 8 giugno 2018, ci sono ancora alcuni browser che non supportano let!

enter image description here


Come tenere traccia del supporto del browser

Per una panoramica aggiornata di quali browser supportano il let dichiarazione al momento della tua lettura di questa risposta, vedi Questo Can I Use pagina.


(*) Le variabili a livello globale e funzionale possono essere inizializzate e utilizzate prima che vengano dichiarate perché le variabili JavaScript sono issato. Ciò significa che le dichiarazioni sono sempre molto al top dello scopo.

(**) Le variabili con scope bloccate non vengono issate


115
2018-06-02 20:59



Alla risposta accettata manca un punto:

{
  let a = 123;
};

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

98
2018-04-17 21:38



Ci sono alcune sottili differenze - let lo scoping si comporta più come l'ambito della variabile fa più o meno qualsiasi altra lingua.

per esempio. Mira al blocco che racchiude, non esistono prima di essere dichiarati, ecc.

Tuttavia vale la pena notare questo let è solo una parte delle più recenti implementazioni di Javascript e ha vari gradi di supporto del browser.


40
2018-03-06 10:41



Ecco un esempio per la differenza tra i due (supporto appena iniziato per chrome): enter image description here

Come puoi vedere var j la variabile ha ancora un valore al di fuori dell'ambito del ciclo for (Block Scope), ma il let i la variabile non è definita al di fuori dell'ambito del ciclo for.

"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

Ambito di blocco

Variabili dichiarate usando il let le parole chiave sono a scope, il che significa che sono disponibili solo nel bloccare in cui sono stati dichiarati.

Al livello superiore (al di fuori di una funzione)

Al livello più alto, le variabili dichiarate usando let non creare proprietà sull'oggetto globale.

var globalVariable = 42;
let blockScopedVariable = 43;

console.log(globalVariable); // 42
console.log(blockScopedVariable); // 43

console.log(this.globalVariable); // 42
console.log(this.blockScopedVariable); // undefined

All'interno di una funzione

All'interno di una funzione (ma al di fuori di un blocco), let ha lo stesso scopo di 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

All'interno di un blocco

Variabili dichiarate usando let all'interno di un blocco non è possibile accedere al di fuori di quel blocco.

{
  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

All'interno di un ciclo

Variabili dichiarate con let nei loop può essere fatto riferimento solo all'interno di quel ciclo.

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.

Loop con chiusure

Se usi let invece di var in un ciclo, con ogni iterazione si ottiene una nuova variabile. Ciò significa che puoi tranquillamente utilizzare una chiusura all'interno di un loop.

// 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);
}

Zona morta temporale

Per colpa di la zona morta temporale, variabili dichiarate usando let non è possibile accedere prima che vengano dichiarati. Il tentativo di farlo genera un errore.

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

No re-declaring

Non puoi dichiarare la stessa variabile più volte usando let. Inoltre, non puoi dichiarare una variabile usando let con lo stesso identificatore di un'altra variabile che è stata dichiarata usando 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 è abbastanza simile a let-è a livello di blocco e ha TDZ. Vi sono, tuttavia, due cose che sono diverse.

Nessun riassegnazione

Variabile dichiarata usando const non può essere riassegnato.

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

Si noti che non significa che il valore è immutabile. Le sue proprietà possono ancora essere modificate.

const obj = {};
obj.a = 42;
console.log(obj.a); // 42

Se vuoi avere un oggetto immutabile, dovresti usare Object.freeze().

Initializer è richiesto

Devi sempre specificare un valore quando dichiari una variabile usando const.

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

37
2018-01-17 15:11