Diego Betto's Blog
Foto di Emily Morter su Unsplash

Diego Betto · 6 settembre 2026 · 3 min di lettura

!function(){}(): cos'è e perché si scrive così una IIFE

Cos'è una IIFE, perché a volte inizia con !, + o void prima di function, e dove si trova ancora oggi nel codice JavaScript.

Condividi:XLinkedInFacebookWhatsApp

Che cos’è una IIFE?

Capita di trovare in una libreria minificata o in un vecchio script una riga così

!(function () {
  console.log("Ciao!");
})();

Sembra un errore di battitura — un punto esclamativo davanti a function — ma è del tutto intenzionale. Questa è una IIFE, acronimo di Immediately Invoked Function Expression: una funzione che viene definita e invocata immediatamente, nello stesso istante.

La forma più comune, quella che si insegna di solito, è questa:

(function () {
  console.log("Ciao!");
})();

Le parentesi tonde intorno alla funzione, seguite da un’altra coppia di parentesi che la invoca. Ma perché !function(){}() funziona allo stesso modo? E soprattutto, perché non basta scrivere semplicemente function(){}()?

Il problema: dichiarazione vs espressione

Prova a scrivere questo in un file JavaScript:

function () {
  console.log("Ciao!");
}();

Ottieni un errore di sintassi. Il motivo è che il motore JavaScript, quando trova la parola chiave function all’inizio di uno statement, si aspetta una dichiarazione di funzione (function nome() {}), non un’espressione. Una dichiarazione di funzione non può essere invocata inline subito dopo la sua definizione: quel () finale non ha senso per il parser in quel contesto.

Per far sì che JavaScript interpreti function(){} come espressione di funzione (qualcosa che produce un valore, quindi invocabile), bisogna far capire al parser che non ci troviamo all’inizio di uno statement. Il modo più noto è racchiudere tutto tra parentesi:

(function () {})();

Ma non è l’unico.

Il trucco degli operatori unari

Qualsiasi operatore unario messo prima di function ottiene lo stesso effetto, perché uno statement non può iniziare con un operatore come !, +, - o void. Il parser capisce quindi che sta leggendo un’espressione, e la funzione che segue viene trattata come function expression invocabile.

!(function () {
  console.log("Eseguita con !");
})();

+(function () {
  console.log("Eseguita con +");
})();

void (function () {
  console.log("Eseguita con void");
})();

Tutte e tre le forme eseguono la funzione immediatamente, esattamente come (function(){})(). Cambia solo il valore restituito dall’intera espressione, che nella pratica quasi nessuno usa:

  • !function(){}() restituisce true (la negazione di undefined, che è falsy).
  • +function(){}() prova a convertire il valore di ritorno in numero (di solito NaN, perché undefined non è convertibile).
  • void function(){}() restituisce sempre undefined, per costruzione — se questo ti suona familiare, è lo stesso principio dell’operatore void spiegato in javascript:void(0), cos’è?.

ℹ️ Occhio al valore di ritorno

Se la tua IIFE deve restituire qualcosa che userai davvero (non solo eseguire codice per gli effetti collaterali), evita !/+ e usa le classiche parentesi (function(){ return x; })().

Dove si trova ancora oggi

Questo pattern compare soprattutto in:

  • Librerie minificate o UMD wrapper, dove ogni carattere risparmiato conta e !function è un byte più corto di (function.
  • Script concatenati senza bundler, dove il carattere iniziale funge anche da protezione: se lo script precedente non termina con un punto e virgola, un’espressione che inizia con ( rischierebbe di essere interpretata come una chiamata di funzione sullo script precedente. Iniziare con !, + o void evita l’ambiguità.
  • Vecchio codice jQuery/plugin, dove l’obiettivo era creare uno scope isolato senza inquinare il namespace globale.

Meglio le alternative moderne

Con i moduli ES (import/export), ogni file ha già il proprio scope isolato: non serve più avvolgere il codice in una IIFE solo per evitare variabili globali. Se stai scrivendo codice nuovo con un bundler moderno, preferisci i moduli. La IIFE resta comunque utile da riconoscere quando la incontri in codice legacy o in bundle di terze parti.

Condividi:XLinkedInFacebookWhatsApp
Diego Betto

Scritto da

Diego Betto

Co-Fondatore & CTO presso PAPION. Senior full-stack engineer specializzato in React, TypeScript, Node.js e sicurezza applicativa.