Qual è la differenza tra l’uso di “let” e “var” per dichiarare una variabile in JavaScript?

ECMAScript 6 ha introdotto la dichiarazione di let . L’ho sentito descritto come una variabile “locale”, ma non sono ancora abbastanza sicuro di come si comporta in modo diverso rispetto alla parola chiave var .

Quali sono le differenze? Quando dovrebbe essere usato su var ?

La differenza è l’ambito. var raggiungere il blocco funzione più vicino e let al blocco più vicino, 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 di essere dichiarate nel loro blocco di chiusura. Come visto nella demo, questo genererà un’eccezione ReferenceError.

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 : '') + '
'; } functionScoped(); blockScoped(); document.getElementById('results').innerHTML = html;
 

let anche usare 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. Il riferimento alla variabile i viene archiviato nella chiusura del gestore di clic, anziché il valore effettivo di i .

Ogni singolo click handler si riferirà allo stesso object perché c'è un solo object 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 invece var come mostrato nel codice qui sotto.

DEMO (testato in Chrome e Firefox 50)

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

Ecco una spiegazione della parola chiave let con alcuni esempi.

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

Questa tabella 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.

Qual è la differenza tra let e var ?

  • Una variabile definita utilizzando un’istruzione var è nota in tutta la funzione in cui è definita, dall’inizio della funzione. (*)
  • Una variabile definita usando un’istruzione let è nota solo nel blocco in cui è definita, dal momento in cui è definita in avanti. (**)

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 è nota solo nel primo ciclo for, ma non prima e dopo. Tuttavia, la nostra variabile i è nota 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 oggi?

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

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

  • Se stai scrivendo codice JavaScript lato server ( Node.js ), puoi tranquillamente usare l'istruzione let .

  • Se stai scrivendo codice JavaScript sul lato client e usi un transpiler (come Traceur ), puoi tranquillamente usare l'istruzione let , 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 !

inserisci la descrizione dell'immagine qui


Come tenere traccia del supporto del browser

Per una panoramica aggiornata di quali browser supportano l'istruzione let al momento della lettura di questa risposta, vedere questa pagina Can I Use .


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

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

Alla risposta accettata manca un punto:

 { let a = 123; }; console.log(a); // ReferenceError: a is not defined 

Ci sono alcune sottili differenze – let scoping si comporti più come l’scope variabile fa più o meno qualsiasi altra lingua.

ad es. Esamina il blocco che li contiene, non esistono prima di essere dichiarati, ecc.

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

Ecco un esempio per la differenza tra i due (supporto appena iniziato per chrome): inserisci la descrizione dell'immagine qui

Come si può vedere la variabile var j ancora un valore al di fuori dell’ambito del ciclo for (Block Scope), ma la variabile let i 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); 

let

Ambito di blocco

Le variabili dichiarate usando la parola chiave let sono a scope, il che significa che sono disponibili solo nel blocco in cui sono state dichiarate.

Al livello superiore (al di fuori di una funzione)

Al livello più alto, le variabili dichiarate usando let non creano proprietà sull’object 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 scope 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

Non è ansible accedere alle variabili dichiarate usando let all’interno di un blocco 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

Le variabili dichiarate con anelli di penetrazione possono essere referenziate 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 si usa let invece di var in un ciclo, con ogni iterazione si ottiene una nuova variabile. Ciò significa che puoi tranquillamente usare 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

A causa della zona morta temporale , le variabili dichiarate usando let non possono essere lette prima di essere dichiarate. 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 è ansible dichiarare la stessa variabile più volte utilizzando let . Non è inoltre ansible 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 -it ha un ambito di blocco e ha TDZ. Vi sono, tuttavia, due cose che sono diverse.

Nessun riassegnazione

La variabile dichiarata usando const non può essere riassegnata.

 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 object 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 
  • Variabile non sollevamento

    let si isserà sull’intero ambito del blocco in cui appaiono. Al contrario, var potrebbe issare come sotto.

     { console.log(cc); // undefined. Caused by hoisting var cc = 23; } { console.log(bb); // ReferenceError: bb is not defined let bb = 23; } 

    In realtà, Per @Bergi, sia var che let vengono issati .

  • Raccolta dei rifiuti

    L’ambito di blocco di let è utile per quanto riguarda le chiusure e la garbage collection per recuperare la memoria. Prendere in considerazione,

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

    Il callback del click handler non ha bisogno hugeData variabile hugeData . Teoricamente, dopo l’ process(..) , l’enorme struttura di dati hugeData potrebbe essere hugeData . Tuttavia, è ansible che alcuni motori JS continuino a mantenere questa enorme struttura, poiché la funzione click ha una chiusura sull’intero ambito.

    Tuttavia, l’ambito del blocco può rendere questa enorme struttura di dati ai garbage collection.

     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 loop

    let in the loop può re-legarlo ad ogni iterazione del ciclo, assicurandosi di riassegnarlo il valore dalla fine della precedente iterazione del ciclo. Prendere in considerazione,

     // print '5' 5 times for (var i = 0; i < 5; ++i) { setTimeout(function () { console.log(i); }, 1000); } 

    Tuttavia, sostituire var con let

     // print 1, 2, 3, 4, 5. now for (let i = 0; i < 5; ++i) { setTimeout(function () { console.log(i); }, 1000); } 

    Perché let creare un nuovo ambiente lessicale con quei nomi per a) l'espressione di inizializzazione b) ogni iterazione (in precedenza per valutare l'espressione di incremento), maggiori dettagli sono qui .

La differenza principale è la differenza di ambito , mentre let può essere disponibile solo all’interno dell’ambito che è stato dichiarato, come in ciclo for, ad esempio è ansible accedere a var al di fuori del loop. Dalla documentazione in MDN (esempi anche da MDN):

let consente di dichiarare variabili limitate nell’ambito del blocco, dell’istruzione o dell’espressione su cui viene utilizzato. Questo è diverso dalla parola chiave var , che definisce una variabile globalmente o localmente a un’intera funzione indipendentemente dall’ambito del blocco.

Le variabili dichiarate da let hanno come scope il blocco in cui sono definite, così come in ogni sotto-blocco contenuto. In questo modo, lascia che funzioni molto come var . La differenza principale è che l’ambito di una variabile var è l’intera funzione di chiusura:

 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 }` 

Al livello più alto di programmi e funzioni, let , a differenza di var , non crea una proprietà sull’object globale. Per esempio:

 var x = 'global'; let y = 'global'; console.log(this.x); // "global" console.log(this.y); // undefined 

Se utilizzato all’interno di un blocco, consente di limitare l’ambito della variabile a quel blocco. Notare la differenza tra var il cui ambito è all’interno della funzione in cui è dichiarato.

 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 

Inoltre, non dimenticare che è la funzione ECMA6, quindi non è ancora completamente supportata, quindi è sempre meglio trasferirla su ECMA5 usando Babel ecc … per maggiori informazioni sul sito babel visita

Ecco un esempio da aggiungere a ciò che altri hanno già scritto. Si supponga di voler creare una serie di funzioni, adderFunctions , in cui ogni funzione accetta un singolo argomento Number e restituisce la sum dell’argomento e l’indice della funzione nell’array. Cercare di generare adderFunctions con un ciclo utilizzando la parola chiave var non funzionerà nel modo in cui qualcuno potrebbe aspettarsi ingenuamente:

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

Il processo precedente non genera la serie di funzioni desiderate perché l’ambito di i si estende oltre l’iterazione del blocco for in cui è stata creata ciascuna funzione. Al contrario, alla fine del ciclo, l’ i nella chiusura di ciascuna funzione fa riferimento al valore di i alla fine del ciclo (1000) per ogni funzione anonima in adderFunctions . Questo non è ciò che volevamo: ora abbiamo una matrice di 1000 diverse funzioni in memoria con esattamente lo stesso comportamento. E se successivamente aggiorniamo il valore di i , la mutazione influenzerà tutte le adderFunctions .

Tuttavia, possiamo riprovare usando la parola chiave let :

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

Questa volta, i è un rimbalzo su ogni iterazione del ciclo for . Ogni funzione ora mantiene il valore di i al momento della creazione della funzione e le funzioni adderFunctions si comportano come previsto.

Ora, l’immagine mescola i due comportamenti e probabilmente vedrai il motivo per cui non è consigliabile mescolare il più recente let e const con la var più vecchia nello stesso script. Ciò potrebbe comportare un codice spettacolare che confonde.

 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 

Non lasciare che questo accada a te. Usa un linter.

NOTA: Questo è un esempio di insegnamento inteso a dimostrare il comportamento var / let nei loop e con le chiusure delle funzioni che sarebbe anche facile da capire. Questo sarebbe un modo terribile per aggiungere numeri. Ma la tecnica generale di acquisizione dei dati nelle chiusure di funzioni anonime potrebbe essere incontrata nel mondo reale in altri contesti. YMMV.

La differenza è nello scopo delle variabili dichiarate con ciascuno.

In practice, there are a number of useful consequences of the difference in scope:

  1. let variables are only visible in their nearest enclosing block ( { ... } ).
  2. let variables are only usable in lines of code that occur after the variable is declared (even though they are hoisted !).
  3. let variables may not be redeclared by a subsequent var or let .
  4. Global let variables are not added to the global window object.
  5. let variables are easy to use with closures (they do not cause race conditions ).

The restrictions imposed by let reduce the visibility of the variables and increase the likelihood that unexpected name collisions will be found early. This makes it easier to track and reason about variables, including their reachability (helping with reclaiming unused memory).

Consequently, let variables are less likely to cause problems when used in large programs or when independently-developed frameworks are combined in new and unexpected ways.

var may still be useful if you are sure you want the single-binding effect when using a closure in a loop (#5) or for declaring externally-visible global variables in your code (#4). Use of var for exports may be supplanted if export migrates out of transpiler space and into the core language.

Esempi

1. No use outside nearest enclosing block: This block of code will throw a reference error because the second use of x occurs outside of the block where it is declared with let :

 { let x = 1; } console.log(`x is ${x}`); // ReferenceError during parsing: "x is not defined". 

In contrast, the same example with var works.

2. No use before declaration:
This block of code will throw a ReferenceError before the code can be run because x is used before it is declared:

 { x = x + 1; // ReferenceError during parsing: "x is not defined". let x; console.log(`x is ${x}`); // Never runs. } 

In contrast, the same example with var parses and runs without throwing any exceptions.

3. No redeclaration: The following code demonstrates that a variable declared with let may not be redeclared later:

 let x = 1; let x = 2; // SyntaxError: Identifier 'x' has already been declared 

4. Globals not attached to 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. Easy use with closures: Variables declared with var do not work well with closures inside loops. Here is a simple loop that outputs the sequence of values that the variable i has at different points in time:

 for (let i = 0; i < 5; i++) { console.log(`i is ${i}`), 125/*ms*/); } 

Specifically, this outputs:

 i is 0 i is 1 i is 2 i is 3 i is 4 

In JavaScript we often use variables at a significantly later time than when they are created. When we demonstrate this by delaying the output with a closure passed to setTimeout :

 for (let i = 0; i < 5; i++) { setTimeout(_ => console.log(`i is ${i}`), 125/*ms*/); } 

... the output remains unchanged as long as we stick with let . In contrast, if we had used var i instead:

 for (var i = 0; i < 5; i++) { setTimeout(_ => console.log(`i is ${i}`), 125/*ms*/); } 

... the loop unexpectedly outputs "i is 5" five times:

 i is 5 i is 5 i is 5 i is 5 i is 5 

May the following two functions show the difference:

 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 is interesting, because it allows us to do something like this:

 (() => { 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++); } } } })(); 

Which results in counting [0, 7].

Whereas

 (() => { 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++); } } } })(); 

Only counts [0, 1].

It also appears that, at least in Visual Studio 2015, TypeScript 1.5, “var” allows multiple declarations of the same variable name in a block, and “let” doesn’t.

This won’t generate a compile error:

 var x = 1; var x = 2; 

Questo sarà:

 let x = 1; let x = 2; 

var is global scope (hoist-able) variable.

let and const is block scope.

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 

If I read the specs right then let thankfully can also be leveraged to avoid self invoking functions used to simulate private only members – a popular design pattern that decreases code readability, complicates debugging, that adds no real code protection or other benefit – except maybe satisfying someone’s desire for semantics, so stop using it. /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 

See ‘ Emulating private interfaces ‘

Some hacks with 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 and setter with 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) 

When Using let

The let keyword attaches the variable declaration to the scope of whatever block (commonly a { .. } pair) it’s contained in. In other words, let implicitly hijacks any block’s scope for its variable declaration.

let variables cannot be accessed in the window object because they cannot be globally accessed.

 function a(){ { // this is the Max Scope for let variable let x = 12; } console.log(x); } a(); // Uncaught ReferenceError: x is not defined 

When Using var

var and variables in ES5 has scopes in functions meaning the variables are valid within the function and not outside the function itself.

var variables can be accessed in the window object because they cannot be globally accessed.

 function a(){ // this is the Max Scope for var variable { var x = 12; } console.log(x); } a(); // 12 

If you want to know more continue reading below

one of the most famous interview questions on scope also can suffice the exact use of let and var as below;

When using let

 for (let i = 0; i < 10 ; i++) { setTimeout( function a() { console.log(i); //print 0 to 9, that is literally AWW!!! }, 100 * i); } 

This is because when using let , for every loop iteration the variable is scoped and has its own copy.

When using var

 for (var i = 0; i < 10 ; i++) { setTimeout( function a() { console.log(i); //print 10 times 10 }, 100 * i); } 

This is because when using var , for every loop iteration the variable is scoped and has shared copy.

let is a part of es6. These functions will explain the difference in easy way.

 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 } 

Previously there were only two scopes in JavaScript, ie functional and global. With ‘ let ‘ keyword JavaScript has now introduced block-level variables.

To have a complete understanding of the ‘let’ keyword, ES6: ‘let’ keyword to declare variable in JavaScript will help.

Now I think there is better scoping of variables to a block of statements using 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 } 

I think people will start using let here after so that they will have similar scoping in JavaScript like other languages, Java, C#, etc.

People with not a clear understanding about scoping in JavaScript used to make the mistake earlier.

Hoisting is not supported using let .

With this approach errors present in JavaScript are getting removed.

Refer to ES6 In Depth: let and const to understand it better.

This article clearly defines the difference between var, let and const

const is a signal that the identifier won’t be reassigned.

let , is a signal that the variable may be reassigned, such as a counter in a loop, or a value swap in an algorithm. It also signals that the variable will be used only in the block it’s defined in, which is not always the entire containing function.

var is now the weakest signal available when you define a variable in JavaScript. The variable may or may not be reassigned, and the variable may or may not be used for an entire function, or just for the purpose of a block or loop.

https://medium.com/javascript-scene/javascript-es6-var-let-or-const-ba58b8dcde75#.esmkpbg9b

ECMAScript 6 added one more keyword to declare variables other the “const” other than “let”.

The primary goal of introduction of “let” and “const” over “var” is to have block scoping instead of traditional lexical scoping. This article explains very briefly difference between “var” and “let” and it also covers the discussion on “const” .

As mentioned above:

The difference is scoping. var is scoped to the nearest function block and let is scoped to the nearest enclosing block , which can be smaller than a function block. Both are global if outside any block.Lets see an example:

Example1:

In my both examples I have a function myfunc . myfunc contains a variable myvar equals to 10. In my first example I check if myvar equals to 10 ( myvar==10 ) . If yes, I agian declare a variable myvar (now I have two myvar variables)using var keyword and assign it a new value (20). In next line I print its value on my console. After the conditional block I again print the value of myvar on my console. If you look at the output of myfunc , myvar has value equals to 20.

let keyword

Example2: In my second example instead of using var keyword in my conditional block I declare myvar using let keyword . Now when I call myfunc I get two different outputs: myvar=20 and myvar=10 .

So the difference is very simple ie its scope.

Check this link in MDN

 let x = 1; if (x === 1) { let x = 2; console.log(x); // expected output: 2 } console.log(x); // expected output: 1