Forem

Cover image for Hoisting: Que bruxaria é essa?!
ananopaisdojavascript
ananopaisdojavascript

Posted on • Edited on

3 1

Hoisting: Que bruxaria é essa?!

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.

Tentando entender...

Vou usar o console.log() para chamar alguma coisa

console.log(a); // ReferenceError: a is not defined
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Mas... e se tivesse declarado um valor em a? O que poderia acontecer?

console.log(a); // undefined
var a = 20;
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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;
Enter fullscreen mode Exit fullscreen mode

... 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;
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode
console.log(soma(20, 30)); // ReferenceError: Cannot access 'soma' before initialization
const soma = function (a, b) {
  return a + b;
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

E aí? Gostaram? Até a próxima anotação.

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read more

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay