Diferença entre var, let e const

Guia definitivo para entender as diferenças entre var, let e const, além de escopo e hoisting


Atualmente há três formas de se declarar variáveis em JavaScript, utilizando as palavras var, let e const. Todas as formas são aceitas, mas a partir da versão ES6/ES2015 do JavaScript uma das medidas que foi adotada foi a utilização da sintaxe com const e let.

Mas o que torna diferente do var? Se você não sabe, este artigo é para você.

Aqui, vou abordar a diferença entre var, let e const com relação ao escopo e hoisting, que é um dos principais problemas que foi solucionado com o const e let.

Antes de mais nada precisamos entender dois conceitos importantes que são escopo e hoisting.

TL;DR

Escopo

É o local onde as variáveis ou expressões são declaradas dentro do código. Por exemplo, uma função cria um escopo, se uma variável for declarada dentro desta função ela não poderá ser acessada fora da função ou dentro de outras funções.

Hoisting

O hoisting foi introduzido no ES6 e foi pensado sobre como o código JavaScript funciona em modo de execução. Para definir o hoisting em palavras simples podemos dizer que todas as declarações de variáveis e funções são movidas para o topo do seu código antes dele ser executado.

Contudo não é isso que realmente acontece, as declarações de variáveis e funções são colocados em memória durante a fase de execução, mas permanece exatamente onde você as declarou no código.

Agora que foi esclarecido esses dois termos vamos falar um pouco sobre as variáveis declaradas com o var.

Var

Antes do ES6 as variáveis eram declaradas com o var, essa era a regra. Todavia havia problemas relacionados a essa declaração, por isso foi necessário o surgimento das duas novas formas. Antes de tudo, vamos entender o comportamento do var e depois discutir seus problemas.

Variáveis com var podem ser redeclaradas e atualizadas

Em outras palavras significa que podemos criar uma variável e alterar o valor que foi atribuído a ela. Isso pode ser feito de duas formas, veja abaixo:

var name = 'Bastião';
var name = 'Bastiana';
 
// ou 
 
var number = 20;
number = 30;

Escopo de var

A declaração utilizando o var tem três escopos: global, de função ou local.

O escopo global é quando a variável é declarada fora de uma função, em outras palavras qualquer variável declarada com var fora de um bloco de função pode ser utilizada em todo o arquivo.

Sob o mesmo ponto de vista, quando a variável for declarada dentro de uma função significa que ela está disponível e pode ser acessada somente dentro da função correspondente.

Veja o exemplo:

var name = 'Bastião';
 
function sayHello() {
  var hello = "Olá!";
}

Aqui a variável name tem escopo global, pois foi declarada fora da função, enquanto a variável hello tem escopo de função por ser declarada dentro da função. Neste sentido, não é possível acessar a variável hello fora da função, se você tentar acessá-la um erro será retornado informando que hello não foi definida.

var name = 'Bastião';
 
function sayHello() {
  var hello = "Olá!";
}
console.log(hello); // helllo is not defined

Hoisting de var

Variáveis de var sofrem o hoisting e vão para o topo do escopo, e elas são inicializadas com o valor de undefined. Vejamos no código abaixo.

var name;
console.log(name); // undefined
name = 'Bastião';

Problemas com o var

O uso do var tem um ponto fraco, que abordarei no código abaixo.

var car = "Fusca";
 
if (true) {
  var car = "Palio";
}
 
console.log(car); // Palio

Inicialmente criamos a variável car e atribuímos o valor “Fusca”, quando chegar no if a variável será redefinida para “Palio”. A princípio você não verá um problema em atualizar o valor de car, mas se tornará um problema a partir do momento em que você não se lembrar de já ter declarado essa variável antes.

Imagine um código com várias linhas, nele é declarado inúmeras variáveis, consequentemente em algum momento você vai se surpreender com o resultado que vai receber e provavelmente poderá causar vários erros de código. Dessa forma é necessário o uso de cont e let.

Se você ainda não visualizou o problema do var no código acima, vou utilizar o mesmo código utilizando let.

Let

Atualmente é a forma mais indicada para criação de variável no lugar do var. Ele resolve o problema de escopo do var que acabei de mostrar acima, bem como mantém o escopo de bloco, evita redeclaração, mas permite alterar o valor da variável.

let name = 'Bastião';
let name = 'Bastiana'; // erro, name já foi declarado
 
// forma correta
 
let number = 20;
number = 30;

Vejamos agora o mesmo código do problema com o var utilizando o let.

let car = "Fusca";
 
if (true) {
  let car = "Palio";
}
 
console.log(car); // Fusca

Perceba que o uso do let impediu a redeclaração da variável car, evitando gerar bugs e resultados inesperados no código.

Escopo de bloco

Antes de mais nada, precisamos falar sobre o escopo de bloco que é o comportamento do let e const.

Um bloco é criado com chaves { }, ou seja, tudo que está dentro das chaves é um bloco. Não confunda com a criação de objetos ={ }.

Escopo de Let

Uma variável declarada com let dentro de um bloco, está disponível somente dentro daquele bloco.

Vejamos no exemplo:

let fruit = 'Maçã';
 
if (true) {
  let animal = "Gato";
  console.log(animal); // retorna Gato
}
console.log(animal); // animal is not defined - animal não foi definido.

Veja que a variável criada com let dentro do bloco retorna um erro dizendo que ela não foi definida, pois let tem escopo de bloco.

Para finalizar o escopo de let com chave de ouro, veja o código a seguir:

let car = "Fusca";
 
if (true) {
  let car = "Palio";
  console.log(car); // retorna "Palio"
}
 
console.log(car); // retorna "Fusca"

Se você olhar rápido vai falar que é o mesmo código anterior que retornou erro informando que a variável não foi definida, mas não é.

Mas porque não ocorre erro? Porque as instâncias de car são tratadas como variáveis diferentes por estarem em escopos diferentes, em outras palavras, pelo simples fato de adicionar um console.log() dentro do bloco if o JavaScript é inteligente o suficiente para diferenciar as variáveis.

Portanto é indicado utilizar let ou invés de var para declaração de variáveis.

Hoisting de Let

Assim como o var, as declarações de let também sofrem o efeito do hoisting, mas diferentes do var que é iniciado com undefined, o let não é inicializada. Sendo assim, se você tentar acessar a variável let antes da sua declaração terá um erro informando que a variável não foi definida.

Const

Variáveis declaradas com const tem os valores constantes, ou seja, não é possível reatribuir outro valor, nem redeclarar a variável. Caso tente reatribuir um valor ou redeclarar a variável um erro será impresso.

const name = 'Bastiana'
name = 'Joana' // Error: Assignment to constant variable
 
// ou
 
const car = 'Fusca'
const car = 'Palio' // Error: Identifier 'car' has already been declared

As declarações de const devem ser inicializadas no momento forem declaradas.

Portanto este comportamento muda quando declaramos um objeto com const, embora os objetos não possam ser atualizados é possível atualizar as propriedades do objeto. Vejamos:

const car = {
  ports: 2,
  name: 'Fusca'
}

Não é possível fazer isso:

car = {
  engine: '2.0',
} // error: Assignment to constant variable.

Porém isso é possível:

car.name = 'Palio'

O código acima atualizará o valor de car.name.

Escopo de const

Da mesma forma que as declarações de let, as declarações de const tem escopo de bloco, ou seja, podem ser acessadas somente dentro do bloco onde foram declaradas.

const fruit = 'Maçã';
 
if (true) {
  const animal = "Gato";
  console.log(animal); // retorna Gato
}
console.log(animal); // animal is not defined - animal não foi definido.

Hoisting de const

Assim como as declarações de let, as de const sofrem hoisting, mas não são inicializadas.

Resumo

Caso não tenha entendido a diferença, aqui vai:

  • Declaração de var, tem escopo global e de função
  • Declaração de let e const tem escopo de bloco.
  • Variáveis com var podem ser atualizadas e redeclaradas dentro do escopo.
  • Variáveis de let podem ser atualizadas, mas não podem ser redeclaradas
  • Variáveis de const não pode ser atualizadas nem redeclaradas novamente
  • Ambas declarações sofrem o hoisting, mas variáveis com var são inicializadas com undefined, e variáveis com let e const não são inicializadas
  • Portando var e let podem ser declaradas sem ser inicializadas
  • Enquanto const precisa de inicialização durante a declaração.

Considerações finais

Por fim, acredito que é importante saber as diferenças nas declarações de variáveis principalmente para quem está iniciando com o JavaScript, assim como entender conceitos como escopo, bloco, hoisting para não ser pego de surpresa quando estiver codando.

Espero que tenham gostado.

Grande abraço.

Comentários