Definição
Hoisting é um comportamento do motor do JS. É quando esse mesmo motor "catapulta" a variável ou função para o topo do escopo. Eu expliquei rapidamente o que é escopo no artigo Var, let e const: Qual é a diferença? e vou deixar o link aqui.
Var, let e const: Qual é a diferença?!?!
ananopaisdojavascript ・ Aug 15 '21 ・ 2 min read
Tentando entender...
Vou usar o console.log()
para chamar alguma coisa
console.log(a); // ReferenceError: a is not defined
Como o motor do JS não sabe do que se trata (é variável? é função? é objeto?), retornou um erro dizendo que a
não existe. Agora, se eu crio uma variável de mesmo nome a
debaixo desse console.log()
, o que será que acontece?!
console.log(a); // undefined
var a;
Eu criei uma variável depois do console.log()
, não a declarei (não coloquei valor algum nela) e retornou undefined
. Por que isso aconteceu?! É porque o motor do JS encontrou essa variável e a jogou para a parte de cima do escopo. É como se eu tivesse criado a variável antes do console.log()
, o que não aconteceu.
var a;
console.log(a); // undefined
Mas... e se tivesse declarado um valor em a
? O que poderia acontecer?
console.log(a); // undefined
var a = 20;
O resultado seria o mesmo. O retorno seria undefined
porque a
apareceu antes de ser declarada. O motor do JS entenderia dessa forma:
var a;
console.log(a); // undefined
a = 20;
Ele entenderia que a variável a
foi criada sem qualquer valor e que a declaração só apareceu depois de ter sido chamada. Muito louco, não? E se eu colocar o console.log()
depois de a
já ter sido declarada, o que vai acontecer?
console.log(a); // undefined
var a = 20;
console.log(a); // 20
Hum... nesse caso o valor aparece normalmente. Tudo por conta de var
que não tem limitação. Talvez seja uma das razões pelas quais seu uso não é recomendado... E por falar em loucura, que tal testar esse raciocínio com let
e const
?
Testando com let
Vou fazer a mesma coisa, só que com let
no lugar de var
. O que será que acontece?!
console.log(a); // ReferenceError: Cannot access 'a' before initialization
let a;
Epa!! A mensagem de erro agora é completamente diferente! Está dizendo que a
não pode ser acessada antes da inicialização! Por que isso aconteceu?! A resposta nos leva ao...
Temporal Dead Zone
Parece nome de filme de terror, mas é que essa mensagem de erro é conhecida na comunidade com esse nome (vai entender...). É o seguinte: o motor do JS reconhece que a variável a
existe, mas que não pode acessá-la antes da declaração, ou seja, existe uma "zona morta" entre a variável e sua declaração. Lembrando que, apesar de podermos fazer declarações de valores diferentes, let
é um pouco mais limitado que var
no que se refere ao escopo. Agora vou declarar um valor para a
e chamar o console.log()
em seguida. O que será que vai acontecer?!
console.log(a); // ReferenceError: Cannot access 'a' before initialization
let a = 123;
console.log(a); // ReferenceError: Cannot access 'a' before initialization
Olha lá! A mensagem de erro permaneceu a mesma! É porque a variável a
foi usada antes de ter sido declarada e o motor do JS pode ter entendido que tem muita variável com o mesmo nome e deveria "frear" essa "bagunça". Lembrando: let
é mais limitado do que var
. O mesmo comportamento se aplica ao const
...
console.log(a); // ReferenceError: Cannot access 'a' before initialization
const a = 123;
... e às expressões de funções
console.log(soma(20, 30)); // TypeError: soma is not a function
var soma = function (a, b) {
return a + b;
}
O que aconteceu? O motor do JS entendeu que a variável soma
foi criada primeiro (com valor indefinido) e que só recebeu o seu "valor" (nesse caso, a função) depois. Por isso a mensagem de erro. Como const
e let
são bem mais limitados, vamos ver o que acontece:
console.log(soma(20, 30)); // ReferenceError: Cannot access 'soma' before initialization
let soma = function (a, b) {
return a + b;
}
console.log(soma(20, 30)); // ReferenceError: Cannot access 'soma' before initialization
const soma = function (a, b) {
return a + b;
}
Acontece exatamente como no caso das variáveis. Essas expressões também não podem ser acessadas antes da inicialização.
E quanto às funções declarativas?!
O comportamento para as funções declarativas será o mesmo das variáveis com var
, só que nesse caso vai mostrar o valor declarado na função:
console.log(soma(20, 30)); // 50
function soma(a, b) {
return a + b;
}
E aí? Gostaram? Até a próxima anotação.
Top comments (0)