Vai al contenuto principale

[Hard] 📄 IIFE

1. Cos'è una IIFE?

IIFE sta per Immediately Invoked Function Expression (espressione di funzione immediatamente invocata). Rispetto a una normale dichiarazione di funzione, avvolge la funzione con un extra () e la esegue immediatamente:

(() => {
console.log(1);
})();

# oppure

(function () {
console.log(2);
})();

Può anche eseguirsi ripetutamente tramite ricorsione fino a quando una condizione di arresto non viene raggiunta, e le parentesi finali () possono passare parametri.

(function myIIFE() {
num += 1;
console.log(num);
return num < 5 ? myIIFE(num) : console.log('finito!!');
})((num = 0));

Nota che una IIFE viene eseguita al momento dell'inizializzazione (o tramite auto-chiamate interne), ma non può essere richiamata direttamente dall'esterno.

2. Perché usare una IIFE?

Scope

Poiché le variabili dichiarate all'interno di una funzione hanno scope limitato a quella funzione, la IIFE può isolare lo stato ed evitare di inquinare le variabili globali:

// globale
const name = 'Yumi';
const Hello = () => {
return `Hello ${name}!`;
};

(() => {
const name = 'Pitt';
const Hello = () => {
return `Hello ${name}!`;
};
console.log(name); // risultato Pitt
console.log(Hello()); // risultato Hello Pitt!
})();

console.log(name); // risultato Yumi
console.log(Hello()); // risultato Hello Yumi!

Variabili e metodi privati (Private variable and methods)

Usando IIFE con closure si possono creare variabili e metodi privati. Ciò significa che lo stato può essere preservato all'interno della funzione e aggiornato ad ogni chiamata (ad esempio, incremento/decremento).

const increment = (() => {
let result = 0;
console.log(result);
const credits = (num) => {
console.log(`Ho ${num} crediti.`);
};
return () => {
result += 1;
credits(result);
};
})();

increment(); // Ho 1 crediti.
increment(); // Ho 2 crediti.

Attenzione: poiché quelle variabili persistono, un uso eccessivo può consumare memoria e ridurre le prestazioni.

Modulo (Module)

Puoi esporre funzionalità in forma di oggetto come pattern modulo. Nell'esempio seguente, puoi incrementare e anche resettare lo stato:

const Score = (() => {
let result = 0;

return {
current: () => {
return result;
},

increment: () => {
result += 1;
},

reset: () => {
result = 0;
},
};
})();

Score.increment();
console.log(Score.current()); // risultato 1 => 0 + 1 = 1
Score.increment();
console.log(Score.current()); // risultato 2 => 1 + 1 = 2
Score.reset();
console.log(Score.current()); // risultato 0 => reset = 0

Un altro stile:

const Score = (() => {
let result = 0;
const current = () => {
return result;
};

const increment = () => {
result += 1;
};

const reset = () => {
result = 0;
};

return {
current: current,
increment: increment,
reset: reset,
};
})();

Score.increment();
console.log(Score.current());
Score.increment();
console.log(Score.current());
Score.reset();
console.log(Score.current());

Un'altra nota: poiché le IIFE vengono eseguite immediatamente, posizionare due IIFE consecutive può rompere l'ASI (Automatic Semicolon Insertion). Quando si concatenano IIFE, aggiungi i punti e virgola esplicitamente.