Categorias
Projetos

JavaScript IIFE como contêiner de códigos

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:

(function (window, document, undefined) {
//
})(window, document);

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:

(function (window, document, undefined) {
//
})(window, document);

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:

(function (window, document, undefined) {
var name = 'Foo';
})(window, document);
console.log(name); // "name" não definido, está em um escopo diferente

Como funciona IIFE

Uma função normal se parece com isso:

var logMyName = function (name) {
console.log(name);
};
logMyName('Foo');

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:

var logMyName = (function (name) {
console.log(name); // Todd
})('Todd');

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

(function () {
})();

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

function () {
}();

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:

!function () {
}();

E existem variantes:

+function () {
}();
-function () {
}();
~function () {
}();

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:

(function (window) {
})(window);

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:

(function (window, document) {
// é possível usar "window" e "document" normalmente
})(window, document);

A resolução de variáveis