In breve
Sommario
Nella sua forma più semplice, questa tecnica mira a racchiudere il codice all'interno di un ambito di funzione .
Aiuta a ridurre le possibilità di:
- scontro con altre applicazioni / librerie
- inquinamento di portata superiore (probabilmente globale)
Essa non rileva quando il documento è pronto - non è una sorta didocument.onload
nonwindow.onload
È comunemente noto come Immediately Invoked Function Expression (IIFE)
oSelf Executing Anonymous Function
.
Codice spiegato
var someFunction = function(){ console.log('wagwan!'); };
(function() { /* function scope starts here */
console.log('start of IIFE');
var myNumber = 4; /* number variable declaration */
var myFunction = function(){ /* function variable declaration */
console.log('formidable!');
};
var myObject = { /* object variable declaration */
anotherNumber : 1001,
anotherFunc : function(){ console.log('formidable!'); }
};
console.log('end of IIFE');
})(); /* function scope ends */
someFunction(); // reachable, hence works: see in the console
myFunction(); // unreachable, will throw an error, see in the console
myObject.anotherFunc(); // unreachable, will throw an error, see in the console
Nell'esempio sopra, qualsiasi variabile definita nella funzione (cioè dichiarata usando var
) sarà "privata" e accessibile SOLO nell'ambito della funzione (come dice Vivin Paliath). In altre parole, queste variabili non sono visibili / raggiungibili al di fuori della funzione. Guarda la demo dal vivo .
Javascript ha l'ambito delle funzioni. "I parametri e le variabili definiti in una funzione non sono visibili al di fuori della funzione e che una variabile definita ovunque all'interno di una funzione è visibile ovunque all'interno della funzione." (da "Javascript: le parti buone").
Più dettagli
Codice alternativo
Alla fine, il codice precedentemente pubblicato poteva anche essere fatto come segue:
var someFunction = function(){ console.log('wagwan!'); };
var myMainFunction = function() {
console.log('start of IIFE');
var myNumber = 4;
var myFunction = function(){ console.log('formidable!'); };
var myObject = {
anotherNumber : 1001,
anotherFunc : function(){ console.log('formidable!'); }
};
console.log('end of IIFE');
};
myMainFunction(); // I CALL "myMainFunction" FUNCTION HERE
someFunction(); // reachable, hence works: see in the console
myFunction(); // unreachable, will throw an error, see in the console
myObject.anotherFunc(); // unreachable, will throw an error, see in the console
Guarda la demo dal vivo .
Le radici
Iterazione 1
Un giorno qualcuno probabilmente pensò "deve esserci un modo per evitare di nominare 'myMainFunction', poiché tutto ciò che vogliamo è eseguirlo immediatamente".
Se torni alle basi, scopri che:
expression
: qualcosa che valuta un valore. vale a dire3+11/x
statement
: riga (e) di codice che fa qualcosa, MA non valuta un valore. vale a direif(){}
Allo stesso modo, le espressioni di funzioni valutano un valore. E una conseguenza (presumo?) È che possono essere immediatamente invocati:
var italianSayinSomething = function(){ console.log('mamamia!'); }();
Quindi il nostro esempio più complesso diventa:
var someFunction = function(){ console.log('wagwan!'); };
var myMainFunction = function() {
console.log('start of IIFE');
var myNumber = 4;
var myFunction = function(){ console.log('formidable!'); };
var myObject = {
anotherNumber : 1001,
anotherFunc : function(){ console.log('formidable!'); }
};
console.log('end of IIFE');
}();
someFunction(); // reachable, hence works: see in the console
myFunction(); // unreachable, will throw an error, see in the console
myObject.anotherFunc(); // unreachable, will throw an error, see in the console
Guarda la demo dal vivo .
Iterazione 2
Il prossimo passo è il pensiero "perché var myMainFunction =
se non lo usiamo nemmeno !?".
La risposta è semplice: prova a rimuoverlo, come di seguito:
function(){ console.log('mamamia!'); }();
Guarda la demo dal vivo .
Non funzionerà perché "le dichiarazioni di funzione non sono invocabili" .
Il trucco è che rimuovendo var myMainFunction =
abbiamo trasformato l' espressione della funzione in una dichiarazione di funzione . Vedi i link in "Risorse" per maggiori dettagli al riguardo.
La domanda successiva è "perché non posso mantenerlo come espressione di funzione con qualcosa di diverso da var myMainFunction =
?
La risposta è "puoi", e in realtà ci sono molti modi in cui potresti farlo: aggiungendo a +
, a !
, a -
, o magari racchiudendo un paio di parentesi (come è ora fatto per convenzione), e altro credo. Per esempio:
(function(){ console.log('mamamia!'); })(); // live demo: jsbin.com/zokuwodoco/1/edit?js,console.
o
+function(){ console.log('mamamia!'); }(); // live demo: jsbin.com/wuwipiyazi/1/edit?js,console
o
-function(){ console.log('mamamia!'); }(); // live demo: jsbin.com/wejupaheva/1/edit?js,console
Quindi, una volta che la modifica pertinente viene aggiunta a quello che un tempo era il nostro "Codice alternativo", torniamo allo stesso identico codice di quello usato nell'esempio "Codice spiegato"
var someFunction = function(){ console.log('wagwan!'); };
(function() {
console.log('start of IIFE');
var myNumber = 4;
var myFunction = function(){ console.log('formidable!'); };
var myObject = {
anotherNumber : 1001,
anotherFunc : function(){ console.log('formidable!'); }
};
console.log('end of IIFE');
})();
someFunction(); // reachable, hence works: see in the console
myFunction(); // unreachable, will throw an error, see in the console
myObject.anotherFunc(); // unreachable, will throw an error, see in the console
Maggiori informazioni su Expressions vs Statements
:
Scopi demistificanti
Una cosa che ci si potrebbe chiedere è "cosa succede quando NON si definisce la variabile" correttamente "all'interno della funzione, ovvero si fa un semplice compito?"
(function() {
var myNumber = 4; /* number variable declaration */
var myFunction = function(){ /* function variable declaration */
console.log('formidable!');
};
var myObject = { /* object variable declaration */
anotherNumber : 1001,
anotherFunc : function(){ console.log('formidable!'); }
};
myOtherFunction = function(){ /* oops, an assignment instead of a declaration */
console.log('haha. got ya!');
};
})();
myOtherFunction(); // reachable, hence works: see in the console
window.myOtherFunction(); // works in the browser, myOtherFunction is then in the global scope
myFunction(); // unreachable, will throw an error, see in the console
Guarda la demo dal vivo .
Fondamentalmente, se a una variabile che non è stata dichiarata nel suo ambito attuale viene assegnato un valore, "una ricerca nella catena dell'ambito si verifica fino a quando non trova la variabile o raggiunge l'ambito globale (a quel punto la creerà)".
In un ambiente browser (rispetto a un ambiente server come nodejs) l'ambito globale è definito window
dall'oggetto. Quindi possiamo fare window.myOtherFunction()
.
Il mio consiglio "Buone pratiche" su questo argomento è di utilizzare sempre var
quando si definisce qualcosa : che si tratti di un numero, oggetto o funzione e anche quando si è nell'ambito globale. Questo rende il codice molto più semplice.
Nota:
- javascript non ha
block scope
(Aggiornamento: variabili locali dell'ambito del blocco aggiunte in ES6 .)
- javascript ha solo
function scope
& global scope
( window
ambito in un ambiente browser)
Maggiori informazioni su Javascript Scopes
:
risorse
Prossimi passi
Una volta ottenuto questo IIFE
concetto, questo porta a module pattern
, che è comunemente fatto sfruttando questo schema IIFE. Divertiti :)