Um pouco de Teoria antes da diversão.
Muitas vezes, um simples princípio não compreendido, pode confundir novatos ou especialistas em JavaScript. Neste artigo, vamos tentar entender melhor um problema comum, que é mais simples do que parece.
Declarações na frente
Antigamente em linguagens como C, se usavam funções ou procedimentos para dividir um programa, mas havia um problema: as declarações deveriam ficar sempre na frente.
Suponha que você queira usar uma função que junta palavras:
Mas temos um problema aqui, não? Essa função não foi definida antes de ser chamada!
O programa retornará um erro, pois juntarPalavras() não foi criada, ou acha que a linguagem deve permitir 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 todas as funções e variáveis eram declaradas antes de serem usadas, sendo assim não se tinha erros de referência.
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. JavaScript faz exatamente isso, o que chamamos de Hoisting.
Hora da diversão
Vamos começar com algo leve, para ir aquecendo os neurônios, veja o seguinte código:
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:
Recebemos um erro bem obvio não acha? Como vamos definir o nome com o valor de meunome se essa variável nem existe ainda?
Agora, deste jeito:
Opa! “undefined”, sacam a jogada?
Isso acontece porque o JavaScript não obriga você a declarar variáveis, permite que você defina as funções em qualquer lugar que você queira, o que lhe permite usar uma função antes de sua definição. O nome hoisting, elevação ou até mesmo içamento, é só um termo especificado, 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.
Já nesta parte iniciamos seu conteúdo como Jonatan.
Este é o mesmo procedimento feito com as funções:
Viram? Ele elevou a declaração var multiplicaNumero, mas como chamamos antes de ele ser iniciado recebemos um erro.
Se mudarmos para:
Recebemos o erro nos dizendo que multiplicaNumero não foi declarado.
Alteramos novamente:
E agora o código executou sem erro 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 prática declarar e/ou iniciar variáveis e funções no início do escopo:
Boas práticas nos levam a caminhos melhores.