Pular para o conteúdo

JavaScript Intermediário #4
Hoisting

Nessa curta publicação, conheça o mecanismo de hoisting, uma característica peculiar da linguagem JavaScript.

Hoje veremos uma característica bastante peculiar do JavaScript e que normalmente é causa de pequenos erros quanto estamos trabalhando com a linguagem: o hasteamento de variáveis, comumente chamado de hoisting.

Hasteamento de variáveis 🙝

No momento de execução de um código JavaScript, toda declaração de variável passam por um processo de hasteamento, isto é, a declaração da variável é elevada para o topo do escopo atribuído de forma automática. Esse processo é comumente chamado de hoisting. O conceito pode ser um pouco confuso a princípio, então, vamos para um exemplo prático. Em JavaScript, é possível declarar uma função e chamá-la logo em seguida, como no exemplo abaixo:

function hello(name) {
  console.log('Hello, ' + name + '!');
}

hello('Max'); // → Hello, Max!

Entretanto, você também pode chamar uma função que ainda não foi declarada. Ou seja, o código acima pode ser reescrito como o abaixo e ainda assim continua funcionando:

hello('Max'); // → Hello, Max!

function hello(name) {
  console.log('Hello, ' + name + '!');
}

Isso acontece porque a declaração da função hello é hasteada ao topo do código. O compilador faz esse processo de forma automática e, por isso, o código continua funcionando normalmente. O mesmo acontece para variáveis declaradas com var. Veja:

console.log(x); // → undefined
var x = 6;
console.log(x); // → 6

Um erro não aconteceu, no entanto, porque a primeira saída foi undefined se a variável é declarada com o valor 6? Bem, isso acontece porque o mecanismo de hoisting do JavaScript somente eleva declarações das variáveis, mas não a atribuíções que as inicializam. Ou seja, o código acima tem um comportamento equivalente ao código abaixo:

var x;
console.log(x); // → undefined
x = 6;
console.log(x); // → 6

Declarações de variáveis locais passam pelo mesmo processo, ou seja, a saída do código abaixo:

var x;

console.log(x);
x = 1;
foo();
console.log(x);

function foo() {
  console.log(x);
  var x = 2;
  console.log(x);
}

Será igual a:

undefined
undefined
2
1

No entanto, o hoisting somente é aplicado em declarações que utilizam var. O mecanismo de hasteamento de variáveis declaradas com let e const não permite a referência de uma variável ainda não declarada e irá lançar um erro do tipo ReferenceError.

Conclusão 🙝

Podemos resumir essa publicação como: o hasteamento de variáveis com var eleva para o topo do código somente a declaração, mas não a definição; enquanto o hasteamento de funções eleva para o topo do código tanto a declaração quando a definição.

Ainda assim, pelos exemplos anteriores, o comportamento de hastear as declarações de variáveis e funções podem levar a resultados confusos e proporcionar um código de difícil leitura. É importante que você siga algumas boas práticas no momento de escrita do código. Elevar as declarações de suas variáveis para o topo do seu respectivo escopo evita confusão com o mecanismo de hoisting, pois seu código deixa-o explícito.

Outra prática importante é a inicialização de um valor na variável sempre que possível. Dessa forma, evita-se valores indefinidos durante a execução e surpresas indesejadas.

Max Naegeler Roecker

Mestre em Ciência da Computação & Desenvolvedor de Software