O que é Hoisting no JavaScript?
Tentarei escrever, com minhas próprias palavras, uma breve explicação do que é hoisting no JavaScript, quais as condições para isso acontecer e erros comuns que cometemos.
Hoisting
Hoisting é um termo que surgiu no mundo do JavaScript a partir do ECMAScript 2015 e, de forma resumida, permite que funções, variáveis e classes possam ser chamadas antes de serem definidas, dependendo de alguns fatores que iremos discutir a seguir.
Hoisting é a habilidade do JavaScript de, em tempo de compilação, armazenar em memória todas as declarações de variáveis e/ou funções para serem utilizadas ao serem chamadas. Isso não significa que as declarações foram fisicamente movidas para o topo do contexto em que se encontram, elas apenas foram alocadas em memória antes da execução do código.
Variáveis
Apenas declarações são hoisted, inicializações não. Isso significa que não é possível atribuir um valor para a variável depois de sua utilização. Em um cenário como esse, a variável terá um valor igual à undefined
.
É importante dizer também que apenas variáveis criadas com var
são hoisted, const
e let
não são. Caso você tente utilizar uma constante (const) antes de sua declaração, a aplicação exibirá um erro de referência.
Exemplos
value = 2024
console.log('Value', value)
// Will show "2024"
var value
console.log('Another Value', anotherValue)
// Will show "undefined"
var anotherValue = 2024
newLet = 2024
console.log('New Let', newLet)
// Will throw an error like this:
// ReferenceError: Cannot access 'newLet' before initialization
let newLet
console.log('Another Let', anotherLet)
// Will throw an error like this:
// ReferenceError: Cannot access 'anotherLet' before initialization
let anotherLet = 2024
console.log('Another Const', anotherConst)
// Will throw an error like this:
// ReferenceError: Cannot access 'anotherConst' before initialization
const anotherConst = 2024
Funções
As declarações de funções em JavaScript são hoisted, mas function expressions não são.
Exemplos
sayHello("John");
function sayHello(name) {
console.log("Hello " + name);
}
// Will show "Hello John"
sayGoodbye("John");
const sayGoodbye = (name) => {
console.log("Goodbye " + name);
};
// Will throw an error like this:
// ReferenceError: Cannot access 'sayGoodbye' before initialization
saySomething("John");
const saySomething = function (name) {
console.log("Something, " + name);
};
// Will throw an error like this:
// ReferenceError: Cannot access 'saySomething' before initialization
Temporal Dead Zone (TDZ)
Variáveis declaras com const
, let
ou class
são consideradas dentro da Temporal Dead Zone TDZ desde o início do bloco até sua declaração. Por isso, ao tentarmos utilizar uma dessas variáveis antes de sua declaração, o JavaScript acaba retornando um ReferenceError
. Mas mais detalhes sobre isso serão abordados em um post no futuro.