Entenda a diferença entre var, let e const no JavaScript

(Last Updated On: 23 de Maio de 2017)

Na maioria das linguagens de programação, o escopo das variáveis locais é vinculado ao bloco onde elas são declaradas. Sendo assim, elas “morrem” ao final da instrução em que estão sendo executadas. Será que isso se aplica também à linguagem JavaScript? Vamos verificar:

var exibeMensagem = function() {
    var mensagemForaDoIf = 'Caelum';
 
    if(true) {
      var mensagemDentroDoIf = 'Alura';
      console.log(mensagemDentroDoIf); // Alura
    }
 
    console.log(mensagemForaDoIf); // Caelum
    console.log(mensagemDentroDoIf); // Alura
}

Estamos declarando duas variáveis em blocos de código diferentes, qual será o resultado? Vamos testar:

exibeMensagem(); // Imprime 'Alura', 'Caelum' e 'Alura'

Se mensagemDentroDoIf foi declarada dentro do if, por que ainda temos acesso a ela fora do bloco desta instrução?

Utilização antes da declaração

Vejamos abaixo outro exemplo de código em JavaScript:

var exibeMensagem = function() {
		mensagem = 'Alura';
		console.log(mensagem);
		var mensagem;
}

Observe que estamos declarando a variável mensagem apenas depois de atribuir um valor e exibí-la no log, será que funciona? Vamos testar!

exibeMensagem(); // Imprime 'Alura'

Funciona! Como é possível usar a variável mensagem antes mesmo de declará-la? Será que o escopo é garantido apenas dentro de onde a variável foi criada?

Entendendo o hoisting

Em JavaScript, toda variável é “elevada/içada” (hoisting) até o topo do seu contexto de execução. Esse mecanismo move as variáveis para o topo do seu escopo antes da execução do código.

No nosso exemplo acima, como a variável mensagemDentroDoIf está dentro de uma function, a declaração da mesma é elevada (hoisting) para o topo do seu contexto, ou seja, para o topo da function.

É por esse mesmo motivo que “é possível usar uma variável antes dela ter sido declarada”: em tempo de execução a variável será elevada (hoisting) e tudo funcionará corretamente.

Declarando variáveis com var

Considerando o conceito de hoisting, vamos fazer um pequeno teste usando uma variável declarada com var antes mesmo dela ter sido declarada:


void function(){
	console.log(mensagem); // Imprime undefined
	var mensagem;
}();

No caso da palavra-chave var, além da variável ser içada (hoisting) ela é automaticamente inicializada com o valor undefined (caso não seja atribuído nenhum outro valor).

Ok, mas qual é o impacto que temos quando fazemos esse tipo de uso?

Imagine que nosso código contenha muitas linhas e que sua complexidade não seja algo tão trivial de compreender.

Às vezes, queremos declarar variáveis que serão utilizadas apenas dentro de um pequeno trecho do nosso código. Ter que lidar com o escopo de função das variáveis declaradas com var (escopo abrangente) pode confundir a cabeça até de programadores mais experientes.

Sabendo das “complicações” que as variáveis declaradas com var podem causar, o que podemos fazer para evitá-las?

Declarando variáveis com let

Foi pensando em trazer o escopo de bloco (tão conhecido em outras linguagens) que o ECMAScript 6 destinou-se a disponibilizar essa mesma flexibilidade (e uniformidade) para a linguagem.

Através da palavra-chave let podemos declarar variáveis com escopo de bloco. Vamos ver:

var exibeMensagem = function() {
    if(true) {
      var escopoFuncao = 'Caelum';
      let escopoBloco = 'Alura';
      console.log(escopoBloco); // Alura
    }
 
    console.log(escopoFuncao); // Caelum
    console.log(escopoBloco);
}

Qual será a saída do código acima?

exibeMensagem(); // Imprime 'Alura', 'Caelum' e dá um erro

Veja que quando tentamos acessar uma variável que foi declarada através da palavra-chave let fora do seu escopo, o erro Uncaught ReferenceError: escopoBloco is not defined foi apresentado.

Portanto, podemos usar tranquilamente o let, pois o escopo de bloco estará garantido.

Declarando variáveis com const

Embora o let garanta o escopo, ainda assim, existe a possibilidade de declararmos uma variável com let e ela ser undefined. Por exemplo:

void function(){
	let mensagem;
	console.log(mensagem); // Imprime undefined
}();

Supondo que temos uma variável que queremos garantir sua inicialização com um determinado valor, como podemos fazer isso no JavaScript sem causar uma inicialização default com undefined?

Para termos esse tipo de comportamento em uma variável no JavaScript, podemos declarar constantes por meio da palavra-chave const. Vamos dar uma olhada no exemplo:

void function(){
	const mensagem = 'Alura';
	console.log(mensagem); // Alura
	mensagem = 'Caelum';
}();

O código acima gera um Uncaught TypeError: Assignment to constant variable, pois o comportamento fundamental de uma constante é que uma vez atribuído um valor a ela, este não pode ser alterado.

Assim como as variáveis declaradas com a palavra-chave let, constantes também tem escopo de bloco.

Além disso, constantes devem ser inicializadas obrigatoriamente no momento de sua declaração. Vejamos alguns exemplos:

// constante válida
const idade = 18;

// constante inválida: onde está a inicialização?
const pi;

No código acima temos o exemplo de uma constante idade sendo declarada e inicializada na mesma linha (constante válida) e um outro exemplo onde o valor não é atribuído na declaração de pi (constante inválida) ocasionando o erro Uncaught SyntaxError: Missing initializer in const declaration.

Conclusão

Graças ao hoisting, variáveis declaradas com a palavra-chave var podem ser utilizadas mesmo antes de sua declaração.

Por outro lado, as variáveis criadas com let só podem ser utilizadas após sua declaração, pois, apesar de serem elevadas, elas não são inicializadas.

Além das variáveis declaradas com var temos a possibilidade de usar constantes por meio da palavra-chave const ou utilizar variáveis com escopo de bloco através da let .

O que achou dessa nova forma de declarar variáveis no JavaScript? Aproveite e deixe o seu comentário 🙂

Um pouco sobre mim

Me chamo Otávio Prado, tenho 22 anos e moro em Campinas – SP

Bacharel em Sistemas de Informação, analista de sistemas, certificado Java 8, atuo profissionalmente no desenvolvimento de software desde 2012, apaixonado por programação, gosto de me aventurar no mundo da tecnologia. Estou sempre buscando evoluir e aprender um pouco a cada dia. Adoro participar da comunidade, conhecer novas pessoas e fazer novas amizades 🙂

FIQUE POR DENTRO

  • Douglas C Pereira

    Parabéns pelo post Otávio, muito bem explicado, não conhecia a declaração de variável com o let, já o const eu conhecia, obrigado pela informação, abraço.

    • Otávio Prado

      Obrigado Douglas, fico feliz que tenha gostado. O feedback dos leitores é super importante para que os posts possam ir melhorando 😀

      Abraço.

  • Thiago U. Sperandio N.

    Muito bom o artigo!

    • Otávio Prado

      Muito obrigado Thiago 🙂

  • Bruno Guilherme

    Bom artigo !

    • Otávio Prado

      Obrigado Bruno!

  • Leonardo Carmônio

    Muito bom, parabéns

    • Otávio Prado

      Muito obrigado Leonardo 🙂

  • Lucas Lopes

    Você acha que o uso de ‘var’ deve acabar e passar apenas utilizar ‘let’ e ‘const’?

    • Otávio Prado

      Olá Lucas, tudo bem? Pergunta interessante.
      As declarações com var podem ser úteis caso seja necessário dar suporte a navegadores em versões mais antigas. Particularmente não vejo outra vantagem em utilizar o var, acredito que a tendência é que mais programadores passem a utilizar declarações com let.

  • Mat M.R.

    “chave let fora do seu escopo, o erro Uncaught ReferenceError: escopoBloco is not “.
    nessa linha não era pra ser ‘var’ no lugar de ‘let’?

    • Otávio Prado

      Olá Mat, tudo bem? A palavra-chave let é que define escopo de bloco às nossas variáveis. Se a variável fosse declarada com var o escopo seria mais abrangente (escopo de função) e não teríamos problema em acessar a variável fora do if.

  • Danilo Gila de Santana

    Explicou de forma clara! Parabéns pelo artigo.

    • Otávio Prado

      Obrigado Danilo 😀

  • Alex Gomes

    Muito bom! Obrigado pelo artigo.

    • Otávio Prado

      Obrigado Alex 🙂

  • Kelvin Feitosa

    Artigo claro e explicativo.
    Não conhecia as declarações com let e const.
    Continue com artigos assim, obrigado.

  • Leandro Takeda

    Belo post Otavio!

  • fernando andrauss

    Olá, muito bom artigo, tenho uma pergunta: qual o suporte dessas declarações? quais navegadores suportam?

Próximo ArtigoConheça o Fred, a nova atualização do Google