w3schools Qual é a diferença entre usar "let" e "var" para declarar uma variável em JavaScript?




var let const javascript (22)

O ECMAScript 6 introduziu a instrução let . Eu ouvi isso descrito como uma variável "local", mas ainda não tenho certeza de como ela se comporta de maneira diferente da palavra-chave var .

Quais são as diferenças? Quando deve ser usado sobre var ?


Qual a diferença entre let e var ?

  • Uma variável definida usando uma instrução var é conhecida em toda a função em que é definida, desde o início da função. (*)
  • Uma variável definida usando uma instrução let só é conhecida no bloco em que é definida, a partir do momento em que é definida em diante. (**)

Para entender a diferença, considere o seguinte código:

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

Aqui, podemos ver que nossa variável j só é conhecida no primeiro loop for, mas não antes e depois. No entanto, nossa variável i é conhecida em toda a função.

Além disso, considere que as variáveis ​​do escopo de bloco não são conhecidas antes de serem declaradas, porque não são hasteadas. Você também não tem permissão para redeclarar a mesma variável no escopo de bloco dentro do mesmo bloco. Isso faz com que as variáveis ​​com escopo de bloco sejam menos propensas a erros do que as variáveis ​​de escopo global ou funcional, que são içadas e que não produzem erros no caso de várias declarações.

É seguro usar o let hoje?

Algumas pessoas argumentam que, no futuro, usaremos somente as instruções let e que as instruções var tornar-se-ão obsoletas. O guru do JavaScript Kyle Simpson escreveu um artigo muito elaborado sobre por que não é esse o caso .

Hoje, no entanto, esse definitivamente não é o caso. Na verdade, precisamos nos perguntar se é seguro usar a declaração let . A resposta para essa pergunta depende do seu ambiente:

  • Se você estiver escrevendo código JavaScript do lado do servidor ( Node.js ), poderá usar com segurança a instrução let .

  • Se você estiver escrevendo código JavaScript do lado do cliente e usar um transpilador (como o Traceur ), poderá usar com segurança a instrução let , no entanto, seu código provavelmente não será o ideal em relação ao desempenho.

  • Se você está escrevendo código JavaScript do lado do cliente e não usa um transpilador, é necessário considerar o suporte ao navegador.

Hoje, 8 de junho de 2018, ainda existem alguns navegadores que não suportam let !

Como acompanhar o suporte ao navegador

Para uma visão geral atualizada de quais navegadores suportam a instrução let no momento da leitura desta resposta, veja esta página Can I Use ?

(*) Variáveis ​​com escopo global e funcional podem ser inicializadas e usadas antes de serem declaradas, porque variáveis ​​JavaScript são hoisted . Isso significa que as declarações estão sempre no topo do escopo.

(**) Variáveis ​​com escopo de bloco não são içadas


Também parece que, pelo menos no Visual Studio 2015, o TypeScript 1.5, "var" permite várias declarações do mesmo nome de variável em um bloco e "let" não.

Isso não gerará um erro de compilação:

var x = 1;
var x = 2;

Isso vai:

let x = 1;
let x = 2;

var é uma variável global (capaz de elevar).

lete consté o escopo do bloco.

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


Que as duas funções seguintes mostrem a diferença:

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
}

  • Variável Não Içando

    let subir para todo o escopo do bloco em que eles aparecem. Por outro lado, var poderia içar como abaixo.

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

    Na verdade, Per @Bergi, Ambos var e let são içados .

  • Coleta de lixo

    O escopo de bloco de let é útil para fechamentos e coleta de lixo para recuperar memória. Considerar,

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

    O retorno de chamada do manipulador de click não precisa da variável hugeData . Teoricamente, depois que o process(..) é executado, a enorme estrutura de dados hugeData pode ser coletada como lixo. No entanto, é possível que algum mecanismo JS ainda tenha que manter essa estrutura enorme, já que a função click tem um fechamento em todo o escopo.

    No entanto, o escopo do bloco pode transformar essa enorme estrutura de dados em lixo coletado.

    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 loops

    let in the loop pode voltar a vinculá-lo a cada iteração do loop, certificando-se de reatribuir o valor a partir do final da iteração do loop anterior. Considerar,

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

    No entanto, substitua var por let

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

    Como let criar um novo ambiente léxico com os nomes de a) a expressão do inicializador b) cada iteração (antes de avaliar a expressão de incremento), mais detalhes estão here .


Agora eu acho que há melhor escopo de variáveis ​​para um bloco de instruções usando 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
}

Eu acho que as pessoas vão começar a usar let aqui depois para que eles tenham um escopo similar em JavaScript como outras linguagens, Java, C #, etc.

As pessoas que não têm um entendimento claro sobre o escopo no JavaScript costumavam cometer o erro antes.

O içamento não é suportado usando let.

Com essa abordagem, erros presentes no JavaScript estão sendo removidos.

Refira-se ao ES6 em Profundidade: let e const para entender melhor.


vamos fazer parte do es6. Essas funções explicarão a diferença de maneira fácil.

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
}

A diferença está no scope das variáveis ​​declaradas com cada uma.

Na prática, há várias conseqüências úteis da diferença de escopo:

  1. letvariáveis ​​são visíveis apenas no bloco delimitador mais próximo ( { ... }).
  2. letvariáveis ​​são utilizáveis ​​apenas em linhas de código que ocorrem após a variável ser declarada (mesmo que sejam içadas !).
  3. letas variáveis ​​não podem ser redeclaradas por uma varou mais subseqüentes let.
  4. letVariáveis globais não são adicionadas ao windowobjeto global .
  5. letvariáveis ​​são fáceis de usar com fechamentos (não causam condições de corrida ).

As restrições impostas letreduzem a visibilidade das variáveis ​​e aumentam a probabilidade de que colisões inesperadas de nomes sejam encontradas antecipadamente. Isso torna mais fácil rastrear e raciocinar sobre as variáveis, incluindo sua reachability (ajudando com a recuperação de memória não utilizada).

Consequentemente, leté menos provável que as variáveis ​​causem problemas quando usadas em programas grandes ou quando as estruturas desenvolvidas de forma independente são combinadas de maneiras novas e inesperadas.

varainda pode ser útil se você tiver certeza de que deseja o efeito de ligação única ao usar um encerramento em um loop (# 5) ou para declarar variáveis ​​globais visíveis externamente em seu código (# 4). O uso de varexportações pode ser suplantado se exportmigrar do espaço do transpilador para a linguagem principal.

Exemplos

1. Não use fora do bloco anexo mais próximo: Este bloco de código lançará um erro de referência porque o segundo uso xocorre fora do bloco onde é declarado com let:

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

Em contraste, o mesmo exemplo com varobras.

2. Sem uso antes da declaração:
Este bloco de código lançará um ReferenceErrorantes que o código possa ser executado porque xé usado antes de ser declarado:

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

Em contraste, o mesmo exemplo com varparses e executa sem lançar exceções.

3. Nenhuma redeclaração: O código a seguir demonstra que uma variável declarada com letnão pode ser redeclarada mais tarde:

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

4. Globals não anexados a 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. Fácil de usar com fechamentos: Variáveis ​​declaradas com varnão funcionam bem com fechamentos dentro de loops. Aqui está um loop simples que gera a seqüência de valores que a variável ipossui em diferentes momentos:

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

Especificamente, isso gera:

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

Em JavaScript, muitas vezes usamos variáveis ​​em um tempo significativamente posterior do que quando elas são criadas. Quando demonstramos isso, atrasando a saída com um fechamento passado para setTimeout:

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

... a saída permanece inalterada enquanto permanecermos let. Em contraste, se tivéssemos usado em var ivez disso:

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

... o loop inesperadamente gera "i é 5" cinco vezes:

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


let é interessante, porque nos permite fazer algo assim:

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

Que resulta na contagem de [0, 7].

Enquanto que

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

Apenas conta [0, 1].


Função Escopo do Bloco VS:

A principal diferença entre vare leté que as variáveis ​​declaradas com funçãovar têm escopo . Considerando que as funções declaradas com letsão escopo de bloco . Por exemplo:

function testVar () {
  if(true) {
    var foo = 'foo';
  }

  console.log(foo);
}

testVar();  
// logs 'foo'


function testLet () {
  if(true) {
    let bar = 'bar';
  }

  console.log(bar);
}

testLet(); 
// reference error
// bar is scoped to the block of the if statement 

variáveis ​​com var:

Quando a primeira função testVaré chamada, a variável foo, declarada com var, ainda é acessível fora da ifinstrução. Essa variável fooestaria disponível em todos os lugares dentro do escopo da testVar função .

variáveis ​​com let:

Quando a segunda função testLeté chamada, a barra de variáveis, declarada com let, só é acessível dentro da ifinstrução. Porque as variáveis ​​declaradas com letsão escopo de bloco (onde um bloco é o código entre chaves if{}, por exemplo for{}, function{}).

let variáveis ​​não são içadas:

Outra diferença entre vare leté variável com declarado com let não seja içada . Um exemplo é a melhor maneira de ilustrar esse comportamento:

variáveis ​​com let não são içadas:

console.log(letVar);

let letVar = 10;
// referenceError, the variable doesn't get hoisted

variáveis com var que se içou:

console.log(varVar);

var varVar = 10;
// logs undefined, the variable gets hoisted

Global letnão se apega a window:

Uma variável declarada letno escopo global (que é um código que não está em uma função) não é adicionada como uma propriedade no windowobjeto global . Por exemplo (este código está no escopo global):

var bar = 5;
let foo  = 10;

console.log(bar); // logs 5
console.log(foo); // logs 10

console.log(window.bar);  
// logs 5, variable added to window object

console.log(window.foo);
// logs undefined, variable not added to window object


Quando deve letser usado var?

Use letmais varsempre que você pode, porque é simplesmente escopo mais específico. Isso reduz os possíveis conflitos de nomenclatura que podem ocorrer ao lidar com um grande número de variáveis. varpode ser usado quando você deseja que uma variável global esteja explicitamente no windowobjeto (sempre considere cuidadosamente se isso é realmente necessário).


Se eu ler as especificações para a direita então let felizmente também pode ser aproveitado para evitar funções de auto invocação usados para simular apenas os membros privados - um padrão de design popular que diminui a legibilidade do código, complica a depuração, que adiciona nenhuma proteção código real ou outro benefício - exceto talvez satisfazer alguém está desejo de semântica, então pare de usá-lo. / 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

Consulte ' Emulando interfaces privadas '


Aqui está um exemplo para a diferença entre os dois (suporte iniciado apenas para chrome):

Como você pode ver, a variável var j ainda possui um valor fora do escopo do loop for (Escopo do Bloco), mas a variável let i é indefinida fora do escopo do loop 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);



Ao usar let

A letpalavra-chave anexa a declaração de variável ao escopo de qualquer bloco (normalmente um { .. }par) em que ela está contida. Em outras palavras, letintercepta implicitamente o escopo de qualquer bloco para sua declaração de variável.

letvariáveis ​​não podem ser acessadas no windowobjeto porque elas não podem ser acessadas globalmente.

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

Ao usar var

var e as variáveis ​​no ES5 têm escopos em funções, o que significa que as variáveis ​​são válidas dentro da função e não fora da própria função.

varvariáveis ​​podem ser acessadas no windowobjeto porque elas não podem ser acessadas globalmente.

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

Se você quiser saber mais continue lendo abaixo

Uma das perguntas mais famosas da entrevista sobre o escopo também pode ser suficiente para o uso exato lete varcomo abaixo;

Ao usar let

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

Isso ocorre porque, ao usar let, para cada iteração de loop, a variável tem escopo e possui sua própria cópia.

Ao usar var

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

Isso ocorre porque, ao usar var, para cada iteração de loop, a variável está no escopo e compartilhou a cópia.


A resposta aceita está faltando um ponto:

{
  let a = 123;
};

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

Aqui está uma explicação da palavra - chave let com alguns exemplos.

deixe funciona muito como var. A principal diferença é que o escopo de uma variável var é toda a função de inclusão

Esta tabela na Wikipedia mostra quais navegadores suportam o Javascript 1.7.

Observe que somente os navegadores Mozilla e Chrome suportam isso. IE, Safari e potencialmente outros não.


Verifique este link no MDN

let x = 1;

if (x === 1) {
let x = 2;

console.log(x);
// expected output: 2
}

console.log(x);
// expected output: 1

Como acima mencionado:

A diferença é o escopo. vartem o escopo definido para o bloco de funções mais próximo e lettem o escopo definido para o bloco anexo mais próximo , que pode ser menor que um bloco de funções. Ambos são globais se estiverem fora de qualquer bloco. Vamos ver um exemplo:

Exemplo 1:

Nos meus dois exemplos, tenho uma função myfunc. myfunccontém uma variável myvarigual a 10. No meu primeiro exemplo eu verifico se myvaré igual a 10 ( myvar==10). Se sim, eu declaro uma variável myvar(agora tenho duas variáveis ​​myvar) usando uma varpalavra-chave e atribuo a ela um novo valor (20). Na próxima linha, imprimo seu valor no meu console. Após o bloco condicional, imprimo novamente o valor de myvarno meu console. Se você olhar para a saída de myfunc, myvartem valor igual a 20.

Example2: No meu segundo exemplo, em vez de usar a varpalavra-chave em meu bloco condicional, declaro myvarusando letkeyword. Agora, quando eu ligar myfunc, recebo duas saídas diferentes: myvar=20e myvar=10.

Portanto, a diferença é muito simples, ou seja, seu escopo.


A diferença é o escopo. var tem o escopo definido para o bloco de funções mais próximo e let tem o escopo definido para o bloco anexo mais próximo, que pode ser menor que um bloco de funções. Ambos são globais se estiverem fora de qualquer bloco.

Além disso, as variáveis ​​declaradas com let não são acessíveis antes de serem declaradas em seu bloco delimitador. Como visto na demonstração, isso lançará uma exceção 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 : '') + '<br />';
}

functionScoped();
blockScoped();

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

Global:

Eles são muito semelhantes quando usados ​​assim fora de um bloco funcional.

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

No entanto, as variáveis ​​globais definidas com let não serão adicionadas como propriedades no objeto de window global window como aquelas definidas com var .

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

Função:

Eles são idênticos quando usados ​​assim em um bloco de funções.

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

Quadra:

Aqui está a diferença. let é visível apenas no loop for() e var é visível para toda a função.

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
}

Redeclaração:

Assumindo o modo estrito, o var permitirá que você reconfirme a mesma variável no mesmo escopo. Por outro lado, let vamos:

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

Existem algumas diferenças sutis - let escopo se comportar mais como o escopo variável faz em mais ou menos outras línguas.

Por exemplo, escopos para o bloco envolvente, eles não existem antes de serem declarados, etc.

No entanto, vale a pena notar que let é apenas uma parte das implementações de Javascript mais recentes e possui vários graus de suporte ao navegador .


Este artigo define claramente a diferença entre var, let e const

const é um sinal de que o identificador não será reatribuído.

let, é um sinal de que a variável pode ser reatribuída, como um contador em um loop ou uma troca de valor em um algoritmo. Também sinaliza que a variável será usada apenas no bloco em que está definida, o que nem sempre é toda a função de contenção.

varagora é o sinal mais fraco disponível quando você define uma variável em JavaScript. A variável pode ou não ser reatribuída, e a variável pode ou não ser usada para uma função inteira, ou apenas para o propósito de um bloco ou loop.

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





let