Vraag Wat is het verschil tussen het gebruik van "let" en "var" om een ​​variabele in JavaScript te declareren?


ECMAScript 6 geïntroduceerd de let uitspraak. Ik heb het beschreven als een "lokale" variabele, maar ik ben nog steeds niet helemaal zeker hoe het zich anders gedraagt ​​dan het var trefwoord.

Wat zijn de verschillen? Wanneer moet let worden gebruikt var?


3238
2018-04-17 20:09


oorsprong


antwoorden:


Het verschil is scoping. var is afgelegd naar het dichtstbijzijnde functieblok en let is scoped naar de dichtstbijzijnde insluitende blok, dat kleiner kan zijn dan een functieblok. Beide zijn globaal als ze zich buiten een blok bevinden.

Ook variabelen gedeclareerd met let zijn niet toegankelijk voordat ze worden aangegeven in hun bijsluiter. Zoals te zien is in de demo, zal dit een ReferenceError-uitzondering opleveren.

demonstratie: 

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>

Globaal:

Ze lijken erg op elkaar als ze buiten dit functieblok worden gebruikt.

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

Algemene variabelen echter gedefinieerd met let zullen niet worden toegevoegd als eigenschappen op de globale window object zoals die zijn gedefinieerd met var.

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

Functie:

Ze zijn identiek wanneer ze op deze manier worden gebruikt in een functieblok.

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

Blok:

Hier is het verschil. let is alleen zichtbaar in de for() loop en var is zichtbaar voor de hele functie.

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
}

herdeclaratie:

Uitgaande van een strikte modus, var kunt u dezelfde variabele opnieuw binnen dezelfde scope declareren. Aan de andere kant, let zal niet:

'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 kan ook worden gebruikt om problemen met sluitingen te voorkomen. Het bindt nieuwe waarde in plaats van een oude referentie te behouden zoals getoond in de onderstaande voorbeelden.

DEMO

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

De bovenstaande code laat een klassiek JavaScript-sluitingsprobleem zien. Verwijzing naar de i variabele wordt opgeslagen in de klik-handlersluiting, in plaats van de werkelijke waarde van i.

Elke handler voor enkele klik zal naar hetzelfde object verwijzen omdat er maar één counterobject is dat 6 bevat, zodat je zes krijgt voor elke klik.

Algemene oplossing is om dit in een anonieme functie te verwerken en door te geven i als argument. Dergelijke problemen kunnen ook nu worden voorkomen door te gebruiken let in plaats daarvan var zoals weergegeven in onderstaande code.

DEMO (Getest in Chrome en 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



Dit is een uitleg van de let trefwoord met enkele voorbeelden.

laat het werken erg op var lijken. Het belangrijkste verschil is dat de scope van een var-variabele de volledige insluitingsfunctie is

Deze tafel op Wikipedia laat zien welke browsers Javascript 1.7 ondersteunen.

Merk op dat alleen Mozilla- en Chrome-browsers dit ondersteunen. IE, Safari en mogelijk anderen niet.


129
2018-02-23 18:35



Wat is het verschil tussen let en var?

  • Een variabele gedefinieerd met behulp van a var verklaring is overal bekend de functie het is gedefinieerd in, vanaf het begin van de functie. (*)
  • Een variabele gedefinieerd met behulp van a let verklaring is alleen bekend in het blok het is gedefinieerd vanaf, vanaf het moment dat het verder wordt gedefinieerd. (**)

Neem de volgende code door om het verschil te begrijpen:

// 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 kunnen we zien dat onze variabele j is alleen bekend in de eerste lus, maar niet voor en na. Maar toch, onze variabele i is bekend in de volledige functie.

Bedenk ook dat variabelen die zijn afgebakend met blokken niet bekend zijn voordat ze worden gedeclareerd omdat ze niet worden gehesen. Het is ook niet toegestaan ​​om dezelfde block scoped variabele binnen hetzelfde blok opnieuw in te stellen. Dit maakt variabelen met blokafhankelijkheid minder foutgevoelig dan globaal of functioneel geschaalde variabelen, die worden gehesen en die geen fouten veroorzaken in het geval van meerdere declaraties.


Is het veilig om te gebruiken let vandaag?

Sommige mensen zouden stellen dat we in de toekomst ALLEEN let-statements zullen gebruiken en dat var-statements verouderd zullen zijn. JavaScript-goeroe Kyle Simpson schreef een zeer uitgebreid artikel over waarom dat niet het geval is.

Vandaag is dat echter zeker niet het geval. Eigenlijk moeten we ons eigenlijk afvragen of het veilig is om het te gebruiken let uitspraak. Het antwoord op die vraag hangt af van uw omgeving:

  • Als u JavaScript-code aan de serverzijde schrijft (Node.js), kunt u het veilig gebruiken let uitspraak.

  • Als u client-side JavaScript-code schrijft en een transponder gebruikt (zoals traceur), kunt u het veilig gebruiken let verklaring, maar uw code is waarschijnlijk alles behalve optimaal met betrekking tot de prestaties.

  • Als u JavaScript-code op de client schrijft en geen transponder gebruikt, moet u de ondersteuning voor de browser overwegen.

Vandaag, 8 juni 2018, zijn er nog steeds enkele browsers die dit niet ondersteunen let!

enter image description here


Hoe browserondersteuning te volgen

Voor een up-to-date overzicht van welke browsers het ondersteunen let verklaring op het moment dat u dit antwoord leest, zie deze Can I Use pagina.


(*) Globaal en functioneel scoped variabelen kunnen worden geïnitialiseerd en gebruikt voordat ze worden gedeclareerd omdat JavaScript-variabelen zijn gehesen. Dit betekent dat aangiften altijd veel tot de top behoren.

(**) Block-scoped-variabelen worden niet gehesen


115
2018-06-02 20:59



Het geaccepteerde antwoord mist een punt:

{
  let a = 123;
};

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

98
2018-04-17 21:38



Er zijn enkele subtiele verschillen - let scoping gedraagt ​​zich meer als variabele scoping doet in min of meer alle andere talen.

bijv. Het gaat naar het omsluitende blok. Ze bestaan ​​niet voordat ze zijn verklaard, enzovoort.

Het is echter vermeldenswaard dat let is slechts een deel van nieuwere Javascript-implementaties en kent verschillende gradaties browser ondersteuning.


40
2018-03-06 10:41



Hier is een voorbeeld voor het verschil tussen beide (ondersteuning net gestart voor chrome): enter image description here

Zoals je kunt zien var j variabele heeft nog steeds een waarde buiten het for-lusbereik (Block Scope), maar de let i variabele is niet gedefinieerd buiten het for-lusbereik.

"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