Por que às vezes algo funciona "antes" de você declarar?
Talvez já tenha acontecido com você: você chama uma função na linha 2 mesmo tendo escrito ela na linha 20... e funciona. Não é mágica: é o hoisting.
Hoisting ("içamento") é o comportamento pelo qual o JavaScript lê seu código e, antes de executá-lo, "sobe" as declarações para o início do seu escopo. É como arrumar a cozinha antes de começar a cozinhar.
Funções declaradas: são içadas por completo
Por isso você pode chamar uma função antes de escrevê-la, sem nada quebrar:
saudar(); // ✅ funciona
function saudar() {
console.log("Olá!");
}
Variáveis com let e const: a "zona morta temporal"
Com as variáveis não é tão amigável. let e const também são içadas, mas o
JavaScript deixa elas "reservadas, porém bloqueadas": você não pode usá-las
antes da linha onde as declara. Se tentar, salta um erro:
// console.log(x); // ❌ ReferenceError
let x = 5;
A esse trecho "proibido" (do início do escopo até a sua declaração) se dá o nome de Temporal Dead Zone (zona morta temporal). No fundo é bom: ele te avisa de uma falha em vez de seguir com um valor estranho.
⚠️ Pegadinha clássica: var mente com um undefined
Com var a coisa entorta. Usar a variável antes de atribuí-la não dá erro:
retorna undefined. E um undefined silencioso é justamente o tipo de bug que
você leva uma hora para encontrar. Mais uma razão para ficar com let e const:
você prefere um erro claro a um undefined traiçoeiro.
Exemplos
Chamamos somar antes de defini-la e mesmo assim dá 5: hoisting em ação
console.log(somar(2, 3)); // 5, mesmo que a definição esteja abaixo
function somar(a, b) {
return a + b;
}