Elevação é nada mais, nada menos do que trazer para o início do escopo a declaração de variáveis e funções.
Ta, mas como funciona?
Calma, vamos aos poucos. De primeira vista pode parecer extremamente complicado mais depois de saber o que está acontecendo, você vai dizer "poxa era só isso!".
Um pouco de Teoria antes da diversão.
JavaScript pode confundir tanto novatos quanto especialistas em outras línguas da mesma forma. Mas muitas vezes é um simples princípio que está por trás do comportamento, só que não é compreendido. Vamos entende-lo melhor e você vera que não só parece lógico, mas simples.
Como acontece com hoisting
, um pedaço aparentemente elaborado e complexo de comportamento que apenas parece coisas complicadas, sem nenhum benefício.
Primeiro vamos dar uma olhada rápida no problema de elevação.
Declarações na frente
Bem, vamos começar do início. No inicio a terra... Opa! Nem tão no começo assim.
Antigamente em linguagens como C, se usavam funções ou procedimentos para quebrar um programa, mas havia um problema, as declarações deveriam ficar sempre na frente.
Vamos ver mais de perto! Suponha que você queira usar uma função que junta palavras, para chama-la usaria:
juntarPalavras('Arco', 'íris');
Mas temos um problema aqui, não? Essa função não foi definida antes de ser chamada! O programa retornara um erro, pois juntarPalavras()
não está definido, ou acha que a linguagem deve permite que você use funções que são definidas no final do código?
Declarar funções no início do programa resolveu o problema por um tempo, pois como todas as funções e variáveis eram declaradas antes de serem usadas, sendo assim não se tinha erros de referência.
Esta abordagem de baixo para cima não se encaixa naturalmente com o caminho de cima para baixo, lemos um programa da função principal para as outras que são chamadas.
Com o tempo os programadores pensaram "Mas por que cargas D'água não fazemos isso mais amigável e fácil de ler?", "por que ler o código de baixo para cima e, não de cima para baixo?". Agora podemos colocar as definições em qualquer lugar do código e usá-los, mesmo antes de realmente serem definidos, que maravilha não?
O que acontece agora é que os compiladores ou até mesmo linguagens runtime leem todo o programa para saber que funções e variáveis você declarou no código. Após isso, a execução real acontece e ele já sabe onde está cada coisa. Jávascript faz exatamente isso, o que chamamos de Hoisting.
O que? Já entendeu como funciona? Ótimo!
Hora da diversão
Vamos começar com algo leve, para ir aquecendo os neurônios, veja o seguinte código:
nome = 'Jonatan';
console.log(nome);
// Jonatan
Até aqui nada de novo, apenas iniciamos a variável nome
com o valor jonatan
e mostramos na tela;
Certo, e que tal tentarmos isso:
var nome = meunome;
console.log(nome);
// ReferenceError: meunome is not defined
Bem, recebemos um erro bem obvio não acha? Como vamos definir nome
com o valor de meunome
se essa variável nem existe ainda!
Agora se fazemos dessa forma:
var nome = meunome;
console.log(nome);
var meunome;
// undefined
Opa! “undefined”, sacam a jogada?
Isso acontece porque o JavaScript não obriga você a declarar variáveis e permite que você defina as funções em qualquer lugar que você gosta e que lhe permite usar uma função antes de sua definição. O nome hoisting
ou elevação
, até mesmo içamento
é só um termo usado, pois ele arranca as declarações até o topo do seu escopo.
Beleza, agora qual a diferença entre declaração e inicialização? Simples:
Aqui apenas declaramos a variável meunome
.
var meunome;
//undefined
Já nesta parte iniciamos seu conteúdo como Jonatan
;
meunome = 'Jonatan';
//Jonatan
E as funções? Com elas é o mesmo procedimento:
console.log(multiplicaNumero(10,10));
var multiplicaNumero = function(a,b) {
return a*b;
}
//TypeError: undefined is not a function
Viram? Ele elevou a declaração var multiplicaNumero
, mas como chamamos antes de ele ser iniciado recebemos um erro.
Se mudarmos:
console.log(multiplicaNumero(10,10));
multiplicaNumero = function(a,b) {
return a*b;
}
//ReferenceError: multiplicaNumero is not defined
Recebemos o erro nos dizendo que multiplicaNumero
não foi declarado.
Alteramos novamente:
console.log(multiplicaNumero(10,10));
function multiplicaNumero (a,b) {
return a*b;
}
// 100
Vemos agora que o código executou sem erro, isso porque toda declaração de função não anônima é elevada para o topo do escopo;
Fácil não é? Com isso aprendemos que é uma boa pratica declarar e/ou iniciar variáveis e funções no inicio do escopo:
var a, foo = 'bar';
var bar = function(){
var foo = 'foo';
console.log('local: '+foo);
};
bar();
console.log('global: '+foo);
já, mata ne