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:
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:
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.
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.
Problemas com o var
O uso do var
tem um ponto fraco, que abordarei no código abaixo.
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.
Vejamos agora o mesmo código do problema com o var utilizando o let
.
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:
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:
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.
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:
Não é possível fazer isso:
Porém isso é possível:
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.
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
econst
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 comundefined
, e variáveis comlet
econst
não são inicializadas - Portando
var
elet
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.