📙

IIFE

IIFE (immediately invoked function expression) é um design pattern que consiste em uma função executada imediatamente após sua definição. Esse termo foi popularizado pelo Ben Alman, antigamente chamava-se self-executing anonymous function, ou self-invoked anonymous function.
Como vimos no artigo
📝
Function Declaration vs Function Expression
existem algumas formas de se declarar funções usando a palavra chave function.
Quando o statement começa com a palavra function, a engine Javascript entende que trata-se de uma function declaration, o que não é o caso aqui, logo, precisamos forçar a engine a tratar essa linha como uma expression, por isso usamos !. Funciona com qualquer operador unário (+,-, ~, etc..)
!function() { alert('function IIFE') }()
Também podemos forçar a função a ser tratada como uma expression usando a palavra chave void.
void function() { console.log('IIFE') }()
Esses são padrões menos comuns de serem vistos quando implementando IIFE's, e dessa forma, também não conseguimos atribuir o valor de retorno das funções à uma variável.
O modelo mais comumente é encapsular a função entre parênteses e então atribuir essa expression a uma variável.
const result = (function() { return 1 }()); console.log(result) // Output: 1
Também podemos omitir o parênteses pois já estamos definindo uma function expression. Porém dificulta a legibilidade do código pois não sugere ao desenvolvedor que trata-se de uma IIFE, sem que este navegue e visualize a última linha da função.
const result = function() { return 1 }(); console.log(result) // Output: 1

Usos

Antes do ES6, não existiam módulos de forma nativa na especificação da linguagem, e funções eram a única forma de criar um escopo privado - ver
🔗
Function Scope, Block Scope and Lexical Scope
.
Esse era um design pattern muito usado para evitar poluir o escopo global, já que também não existiam const e let, e o block scope.
(function() { var scoped = 1; }()); console.log(scoped); // ReferenceError
Outro uso muito comum era o module pattern, que permitia simular o conceito de classes, de tal forma que fosse possível incluir variáveis e métodos públicos e privados, protegendo algumas partes do código do escopo superior.
Na época não existia o conceito de privacidade no Javascript, pois não era possível definir variáveis e métodos privados como em outras linguagens, logo era preciso criar um outro escopo para simular esse comportamento.
var module = (function() { // variável acessível apenas dentro da IIFE var counter = 0; function increment() { counter++; } // API pública return { increment: increment } }()); var counter = module() counter.increment()
Por fim, quando se era necessário usar um loop for, por exemplo, uma IIFE também era necessária.
for (var i = 0; i < 2; i++) { const button = document.createElement('button'); button.innerText = 'Button ' + i; button.onclick = function() { console.log(i); }; document.body.appendChild(button); } console.log(i); // 2
Ao clicar nos dois botões o mesmo alerta é disparado: 2, pois a variável i é global, e seu último valor foi 2. Para corrigir esse problema antes do ES6, uma IIFE era usada
for (var i = 0; i < 2; i++) { const button = document.createElement('button'); button.innerText = 'Button ' + i; button.onclick = (function(copyOfI) { return () => { console.log(copyOfI); }; })(i); document.body.appendChild(button); } console.log(i); // 2

Referências