Os segredos da IIFE
Quando uma função imediata é invocada, muita coisa pode estar acontecendo por trás dessa chamada. Quer descobrir o que é? Então me acompanhe na leitura :D
Pra quem não conhece, a IIFE ou Imediately Invoked Function Expression (Expressão de Função Invocada Imediatamente), faz exatamente isso: no momento em que ela é interpretada, ela é imediatamente invocada, para que o seu conteúdo seja executado!
E porque é tão importante usar IIFE?
Formato da IIFE
Antes de qualquer coisa, vou mostrar como se utiliza uma IIFE. Para uma função simples, você pode invocá-la da seguinte maneira:
1 | function sayHi() { |
Quando você cria uma função, ela não faz nada até que seja invocada. Quando criamos a função sayHi()
, ela só vai responder com um "hi!"
quando a invocarmos! Na linha 5
do código acima, nós estamos usando os parênteses ()
para invocar a função. Quando fazemos isso, nos é retornado a string hi!
.
Ou seja, essa função precisa de um momento específico para ser invocada.
A IIFE é invocada imediatamente. Mas para que façamos a invocação de uma função imediata, precisamos transformá-la em uma expressão. Nesse caso, vamos utilizar os parênteses para transformar a função em uma expressão, e depois usar novamente os parênteses para invocá-la:
1 | ;(function( win, undefined ) { |
Essa é uma IIFE! É uma função anônima, logo, ela não poderia ser invocada, pois não tem um nome. Mas quando a transformamos em uma expressão, podemos invocá-la assim que ela é interpretada. Se executar esse código no seu console, você verá como resultado, a string "hi!"
!
Você pode ler esse post se tiver interesse em saber mais sobre invocações de funções :)
Mas porque eu usaria uma IIFE? E o ponto-e-vírgula no ínicio? E aqueles parâmetros? E porque o undefined
como parâmetro?
Porque usar IIFE
Escopo. O Javascript tem um problema bastante grave, que é a questão do escopo. Tudo o que você declara fora de uma função, faz parte do escopo global. Algumas linguagens colocam escopo a partir de blocos (if
, while
, for
, etc). Mas em Javascript, se você declarar uma variável dentro de um if
, você ainda será capaz de consultar o seu valor, pois o escopo é definido por um bloco de função.
Então, o motivo de usar uma IIFE é para que o seu código não fique sujando o escopo global, e evitar que suas variáveis possam colidir com outras de mesmo nome, que estão no mesmo escopo.
Criando uma função, a função ou variável criada ali dentro (utilizando o var
), fará parte do escopo local, e não poderá ser acessada de fora, a não ser que, explicitamente, você a exporte.
Ponto-e-vírgula no início da IIFE
O ponto-e-vírgula no início da IIFE é usado como segurança. Como você deve saber, você precisa colocar um ponto-e-vírgula sempre ao final de cada expressão. Mas ele não é obrigatório.
Então, imagine você concatenando todos os seus scripts, junto com as libs de terceiros que você usa. E imagine que uma lib qualquer tem, na última linha do seu código, a seguinte expressão:
1 | export = service |
Sem colocar o ponto-e-vírgula no final. Quando você chamar a sua IIFE sem o ponto-e-vírgula no início, a sua expressão vai juntar com o service
, fazendo-o se transformar em uma função, e causando um efeito colateral indesejado:
1 | export = service(function( win, undefined ) { |
Entende a “gravidez”(:P) do problema? Agora, e se você colocar o ponto-e-virgula?
1 | export = service;(function( win, undefined ) { |
Aí sim, tudo irá funcionar como o esperado! :D
Parâmetros
Como qualquer função normal, você pode, ao invocar a IIFE, passar parâmetros para ela. O motivo de passar parâmetros é também escopo. Você pode passar um parâmetro que está no escopo global, para que ele seja usado como uma variável local. Um exemplo bastante comum é o jQuery:
1 | ;(function( $ ) { |
Assim você injeta como parâmetro o objeto global jQuery
, e recebe na IIFE como $
, localmente, que agora pode ser usado sem medo de conflitar com qualquer outra lib que utilizar $
. xD
O undefined na IIFE
Muitas pessoas não sabem, mas o undefined
não é um operador, como o new
ou o void
, mas sim uma variável global, que tem valor indefinido (undefined
).
Por esse motivo, no EcmaScript 3, era permitido mudar o valor de undefined
.
O código abaixo era perfeitamente válido:
1 | undefined = true; |
Bizarro, não? Já na EcmaScript 5, com o strict mode ativado, ("use strict"
), esse problema é resolvido, e undefined
se torna imutável. Maaaas, como nem todo código usa o "use strict"
, e você nunca sabe se alguém pode ter mexido no valor de undefined
, nós passamos na IIFE o parâmetro undefined
sem referenciar objeto algum. Logo, o seu valor, localmente - dentro da IIFE - será undefined
!
1 | undefined = true; |
Compreendeu o problema? Usando a IIFE, você está sempre seguro desse valor :D
Era isso que eu queria mostrar hoje, espero que o assunto tenha ficado claro! :)
Se não ficou, poste nos comentários! :)
Até o próximo :D
Sobre o #1postperday: https://blog.da2k.com.br/2014/12/31/um-post-por-dia/
Tem alguma sugestão para os próximos posts do #1postperday? Deixe ela aqui: https://github.com/fdaciuk/fdaciuk.github.io/issues/1