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 🙂

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