JavaScript puro ou Vanilla JavaScript (felizmente) está voltando. E com força. Aqui, mesmo, no desenvolvimento para web, você consegue encontrar vários artigos mostrando como é possível fazer tudo o que você faz com bibliotecas de centenas de KB com poucas linhas de código.

Mas, quando você decide continuar nos estudos e começa a inspecionar códigos alheios, inevitavelmente você se depara com algo como:

E você encontra isso em diversos códigos; e vê outros desenvolvedores indicando; e colegas dizendo que esta é uma boa prática. Mas você sabe o que, realmente, isso significa? Continue lendo.

Frequentemente desenvolvedores descobrindo (ou redescobrindo) o JavaScript puro se perguntam sobre IIFE (Expressão de Função Imediatamente Invocada ou Immediately-Invoked Function Expression), frequentemente apresentado da seguinte maneira:

Na verdade, várias coisas estão acontecendo aí. Analisemos cada uma delas.

Escopo privado em IIFE

JavaScript tem maneiras interessantes de trabalhar com escopo de função; então, primeiramente essa expressão cria um “âmbito privado” (private scope). Por exemplo:

Como funciona IIFE

Uma função normal se parece com isso:

Ela é chamada (invoke) quando necessário, por escolha do programador, em qualquer ponto do código em que se queira e/ou seja possível.

A razão pela qual essa IIFE em JavaScript foi criada, foi para ser uma expressão de função imediatamente invocada, o que significa que elas são imediatamente chamadas em tempo de execução – também, não é possível chamá-la novamente, já que elas só rodam uma vez, mais ou menos assim:

O pulo-do-gato aqui é isso (que já foi atribuído a uma variável no exemplo anterior):

O par de parênteses extra é necessário. Isso não funciona:

Embora existam vários truques que podem ser feitos para “enganar” o JavaScript e fazê-lo funcionar. Este, por exemplo, força o parser de JavaScript a tratar o código que segue ! como uma expressão:

E existem variantes:

Mas não é preciso se forçar a decorar isso para usar a todo momento para fazer uma IIFE.

Argumentos da IIFE

Agora que foi explicado como isso funciona, passemos para os argumento da IIFE:

Como isso funciona? Lembre-se, (window); é onde a função é chamada, e onde é passado o Objeto window. Então ele é passado para a função – que também foi chamada de window.

Então, o que mais é possível fazer? Passar tudo o que for necessário! Por exemplo, passar o Objeto document:

A resolução de variáveis ​​locais é mais rápida que a de variáveis ​​globais, mas esta está numa escala enorme e dificilmente alguém vai perceber o aumento da velocidade – mas vale a pena considerar se há muitas referências a globais!

E sobre o undefined?

Em ECMAScript 3, undefined é mutável. Isso significa que o valor poderia ser transferido com, por exemplo, undefined = true;…! Felizmente, no ECMAScript 5 em modo estrito ('use strict';) o parser lança um erro quando se depara com isso. Antes disso, começou-se a proteger uma IIFE da maneira já vista:

O que significa que se alguém fizesse isso estaria tudo bem:

Minificando

Ao minificar as variáveis ​​locais é que a grandiosidade do padrão IIFE realmente pode ser vista. Nomes de variáveis ​​locais não são realmente necessários se estas foram passadas dessa maneira​​, então, é possível dar o nome que quiser para elas.

Por exemplo, mudar disso:

Pra isso:

Imagine todas as referências a bibliotecas e window e document minificadas. Claro que você não precisa parar por aí; é possível passar jQuery, também, ou qualquer outra coisa que esteja disponível dentro no escopo léxico:

JavaScript IIFE é como um contêiner de códigos

Isso também significa que você não precisa chamar jQuery.noConflict(); ou qualquer coisa como $ é atribuído localmente ao módulo. Aprender como escopos e variáveis ​​globais/locais funcionam ajuda ainda mais.

Passar o código por um bom minificador certamente garantirá a renomeação de undefined para c (por exemplo, e apenas se for usado). É importante atentar para o fato de que o nome undefined é irrelevante; só é preciso saber que o Objeto referenciado é indefinido (undefined) e, como undefined não tem qualquer significado especial – undefined é o valor que o JavaScript dá às coisas que são declaradas mas não têm nenhum valor (nem em IIFE).

Ambientes globais não-navegador

Devido a algumas tecnologias, Node.js, o navegador não é sempre o Objeto global, o que pode ser realmente problemático se você está tentando criar uma IIFE para funcionar em múltiplos ambientes. Por esta razão, há determinadas “alternativas”, como isso:

Em um navegador, o ambiente global this se refere ao Objeto window, de modo que não é preciso passar em window, é sempre possível reduzir para this.

Alguns preferem o nome root, já que ele pode se referir tanto a ambientes não-navegador, quanto à raiz do browser.

Se você estiver interessado em uma solução universal (muito útil para ser usada para a criação de módulos em projetos de código aberto) é o UMD (Universal Module Definition):

A função está sendo invocado com outra função sendo passada para ela. É possível, então, atribuí-la ao ambiente relevante “de dentro”. No navegador, root.MYMODULE = factory(); é o módulo IIFE; em qualquer outro ambiente (como Node.js), será usado module.exports ou requireJS se define === 'function' && define.amd resolver como true.

Mas isso é assunto para outro artigo. Por enquanto, só dê uma olhada no repositório do UMD.

Conclusão

Como foi visto, usar IIFE (Expressão de Função Imediatamente Invocada ou Immediately-Invoked Function Expression) é extramente benéfico. Além de ajudar na performance, por permitir que não seja preciso lookups no código a procura de variáveis globais, permite que seu código possa ficar “isolado”, protegendo o escopo de uma porção de código ou módulo do ambiente em que foi colocado.

O fato de diversos frameworks e bibliotecas JavaScript de renome como jQuery, Backbone.js, Modernizr e outros usarem IIFE já é bastante significativo. Use código de qualidade para fazer código de qualidade.