In javascript, quando vorresti usare questo:
(function(){
//Bunch of code...
})();
oltre questo:
//Bunch of code...
In javascript, quando vorresti usare questo:
(function(){
//Bunch of code...
})();
oltre questo:
//Bunch of code...
Risposte:
Si tratta di scoping variabile. Le variabili dichiarate nella funzione di auto-esecuzione sono, per impostazione predefinita, disponibili solo per il codice all'interno della funzione di auto-esecuzione. Ciò consente di scrivere il codice senza preoccuparsi di come le variabili vengono denominate in altri blocchi di codice JavaScript.
Ad esempio, come menzionato in un commento di Alexander :
(function() {
var foo = 3;
console.log(foo);
})();
console.log(foo);
Questo prima registrerà 3
e poi lancerà un errore sul successivo console.log
perché foo
non è definito.
var
, in questo modo: ...function(){ foo=3;}
? Impostarebbe una variabile globale, giusto?
function(){ var foo = 3; alert(foo); }; alert(foo);
quindi ancora non capisco
Semplicistico. Quindi aspetto molto normale, è quasi confortante:
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
Tuttavia, cosa succede se includo una libreria JavaScript davvero utile nella mia pagina che traduce i caratteri avanzati nelle loro rappresentazioni di livello base?
Aspetta cosa?
Voglio dire, se qualcuno digita un personaggio con una sorta di accento, ma voglio solo caratteri "inglesi" AZ nel mio programma? Bene ... i caratteri "é" spagnoli e "é" francesi possono essere tradotti in caratteri base di "n" ed "e".
Quindi una persona gentile ha scritto un convertitore di caratteri completo che posso includere nel mio sito ... Lo includo.
Un problema: ha una funzione chiamata 'nome' come la mia funzione.
Questo è ciò che si chiama collisione. Abbiamo due funzioni dichiarate nello stesso ambito con lo stesso nome. Vogliamo evitare questo.
Quindi dobbiamo in qualche modo estendere il nostro codice.
L'unico modo per ottenere il codice scope in javascript è racchiuderlo in una funzione:
function main() {
// We are now in our own sound-proofed room and the
// character-converter libarary's name() function can exist at the
// same time as ours.
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
}
Questo potrebbe risolvere il nostro problema. Ora tutto è racchiuso e vi si può accedere solo dalle nostre parentesi graffe di apertura e chiusura.
Abbiamo una funzione in una funzione ... che è strana da guardare, ma totalmente legale.
Un solo problema. Il nostro codice non funziona. La nostra variabile userName non viene mai ripetuta nella console!
Possiamo risolvere questo problema aggiungendo una chiamata alla nostra funzione dopo il nostro blocco di codice esistente ...
function main() {
// We are now in our own sound-proofed room and the
// character-converter libarary's name() function can exist at the
// same time as ours.
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
}
main();
O prima!
main();
function main() {
// We are now in our own sound-proofed room and the
// character-converter libarary's name() function can exist at the
// same time as ours.
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
}
Una preoccupazione secondaria: quali sono le possibilità che il nome 'main' non sia ancora stato usato? ... molto, molto magro.
Abbiamo bisogno di PIÙ scoping. E un modo per eseguire automaticamente la nostra funzione main ().
Ora arriviamo alle funzioni di auto-esecuzione (o auto-esecuzione, auto-corsa, qualunque cosa).
((){})();
La sintassi è imbarazzante come peccato. Tuttavia funziona.
Quando si racchiude una definizione di funzione tra parentesi e si include un elenco di parametri (un altro set o parentesi!) Si comporta come una chiamata di funzione .
Vediamo quindi di nuovo il nostro codice, con qualche sintassi auto-eseguita:
(function main() {
var userName = "Sean";
console.log(name());
function name() {
return userName;
}
}
)();
Quindi, nella maggior parte dei tutorial che leggi, ora sarai bombardato dal termine "auto-esecuzione anonima" o qualcosa di simile.
Dopo molti anni di sviluppo professionale, ti consiglio vivamente di nominare ogni funzione che scrivi per scopi di debug.
Quando qualcosa va storto (e lo farà), controllerai la backtrace nel tuo browser. È sempre più semplice restringere i problemi del codice quando le voci nella traccia dello stack hanno nomi!
Molto prolisso e spero che sia d'aiuto!
:)
L'auto-invocazione (nota anche come auto-invocazione) è quando una funzione viene eseguita immediatamente dopo la sua definizione. Questo è un modello di base e funge da base per molti altri modelli di sviluppo JavaScript.
Sono un grande fan :) perché:
Enorme - (Perché dovresti dire che è buono?)
Più qui .
Namespacing. Gli ambiti di JavaScript sono a livello di funzione.
Non posso credere che nessuna delle risposte menzioni i globuli impliciti.
Il (function(){})()
costrutto non protegge dai globi impliciti, che per me è la preoccupazione maggiore, vedi http://yuiblog.com/blog/2006/06/01/global-domination/
Fondamentalmente il blocco funzione assicura che tutti i "parametri globali" dipendenti che hai definito siano confinati nel tuo programma, non ti protegge dalla definizione di globali impliciti. JSHint o simili possono fornire consigli su come difendersi da questo comportamento.
La var App = {}
sintassi più concisa fornisce un livello di protezione simile e può essere racchiusa nel blocco funzione su pagine "pubbliche". (vedi Ember.js o SproutCore per esempi reali di librerie che usano questo costrutto)
Per quanto riguarda le private
proprietà, sono in qualche modo sopravvalutate a meno che non si stia creando una struttura pubblica o una biblioteca, ma se è necessario implementarle, Douglas Crockford ha delle buone idee.
Ho letto tutte le risposte, qui manca qualcosa di molto importante , BACIO. Ci sono 2 motivi principali, perché ho bisogno di funzioni anonime auto-eseguite, o meglio detto " Espressione della funzione immediatamente invocata (IIFE) ":
Il primo è stato spiegato molto bene. Per il secondo, si prega di studiare il seguente esempio:
var MyClosureObject = (function (){
var MyName = 'Michael Jackson RIP';
return {
getMyName: function () { return MyName;},
setMyName: function (name) { MyName = name}
}
}());
Attenzione 1: Non stiamo assegnando una funzione a MyClosureObject
, più ulteriormente il risultato dell'invocazione di quella funzione . Essere consapevoli ()
dell'ultima riga.
Attenzione 2: ciò che devi sapere sulle funzioni in Javascript è che le funzioni interne hanno accesso ai parametri e alle variabili delle funzioni, all'interno delle quali sono definite.
Proviamo alcuni esperimenti:
Posso MyName
usare getMyName
e funziona:
console.log(MyClosureObject.getMyName());
// Michael Jackson RIP
Il seguente approccio ingegnoso non funzionerebbe:
console.log(MyClosureObject.MyName);
// undefined
Ma posso impostare un altro nome e ottenere il risultato atteso:
MyClosureObject.setMyName('George Michael RIP');
console.log(MyClosureObject.getMyName());
// George Michael RIP
Modifica: nell'esempio sopra MyClosureObject
è progettato per essere utilizzato senza il new
prefisso, quindi per convenzione non dovrebbe essere maiuscolo.
Esiste un parametro e il "Mazzo di codice" restituisce una funzione?
var a = function(x) { return function() { document.write(x); } }(something);
Chiusura. Il valore di something
viene utilizzato dalla funzione assegnata a a
. something
potrebbe avere un valore variabile (per loop) e ogni volta che a ha una nuova funzione.
var x = something;
nella funzione esterna rispetto x
a un parametro, però: imo è più leggibile in questo modo ...
x
e dipendi direttamente dall'ambito lessicale, ovvero document.write(something)
...
Scope isolamento, forse. In modo che le variabili all'interno della dichiarazione della funzione non inquinino lo spazio dei nomi esterno.
Ovviamente, su metà delle implementazioni di JS là fuori, lo faranno comunque.
Ecco un solido esempio di come potrebbe essere utile una funzione anonima auto-invocante.
for( var i = 0; i < 10; i++ ) {
setTimeout(function(){
console.log(i)
})
}
Produzione: 10, 10, 10, 10, 10...
for( var i = 0; i < 10; i++ ) {
(function(num){
setTimeout(function(){
console.log(num)
})
})(i)
}
Produzione: 0, 1, 2, 3, 4...
let
posto del var
primo caso andrà bene.
Poiché le funzioni in Javascript sono oggetti di prima classe, definendolo in questo modo, definisce in modo efficace una "classe" molto simile a C ++ o C #.
Tale funzione può definire variabili locali e avere funzioni al suo interno. Le funzioni interne (efficacemente metodi di istanza) avranno accesso alle variabili locali (effettivamente variabili di istanza), ma saranno isolate dal resto dello script.
Funzione auto-invocata in javascript:
Un'espressione auto-invocante viene invocata (avviata) automaticamente, senza essere chiamata. Un'espressione auto-invocante viene invocata subito dopo la sua creazione. Questo è sostanzialmente usato per evitare conflitti di denominazione e per ottenere l'incapsulamento. Le variabili o gli oggetti dichiarati non sono accessibili al di fuori di questa funzione. Per evitare i problemi di minimizzazione (nomefile.min) utilizzare sempre la funzione auto-eseguita.
Le funzioni di auto-esecuzione vengono utilizzate per gestire l'ambito di una variabile.
L'ambito di una variabile è l'area del programma in cui è definita.
Una variabile globale ha portata globale; è definito ovunque nel tuo codice JavaScript ed è accessibile da qualsiasi parte dello script, anche nelle tue funzioni. D'altra parte, le variabili dichiarate all'interno di una funzione sono definite solo all'interno del corpo della funzione. Sono variabili locali, hanno ambito locale e sono accessibili solo all'interno di quella funzione. I parametri di funzione contano anche come variabili locali e sono definiti solo all'interno del corpo della funzione.
Come mostrato di seguito, è possibile accedere alla variabile variabile globale all'interno della funzione e inoltre notare che all'interno del corpo di una funzione, una variabile locale ha la precedenza su una variabile globale con lo stesso nome.
var globalvar = "globalvar"; // this var can be accessed anywhere within the script
function scope() {
alert(globalvar);
localvar = "localvar" //can only be accessed within the function scope
}
scope();
Quindi sostanzialmente una funzione di auto-esecuzione consente di scrivere il codice senza preoccuparsi di come le variabili sono nominate in altri blocchi di codice javascript.
(function(){
var foo = {
name: 'bob'
};
console.log(foo.name); // bob
})();
console.log(foo.name); // Reference error
In realtà, la funzione sopra sarà trattata come espressione di funzione senza un nome.
Lo scopo principale di avvolgere una funzione con parentesi chiusa e aperta è quello di evitare di inquinare lo spazio globale.
Le variabili e le funzioni all'interno dell'espressione della funzione sono diventate private (ovvero) non saranno disponibili al di fuori della funzione.
La risposta breve è: prevenire l'inquinamento dell'ambito globale (o superiore).
IIFE (Espressioni di funzione immediatamente invocate) è la migliore pratica per scrivere script come plug-in, componenti aggiuntivi, script utente o qualunque script che dovrebbe funzionare con gli script di altre persone . Ciò garantisce che qualsiasi variabile definita non dia effetti indesiderati su altri script.
Questo è l'altro modo di scrivere l'espressione IIFE. Personalmente preferisco questo seguente metodo:
void function() {
console.log('boo!');
// expected output: "boo!"
}();
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/void
Dall'esempio sopra è molto chiaro che IIFE può anche influenzare l'efficienza e le prestazioni, perché la funzione che dovrebbe essere eseguita una sola volta verrà eseguita una volta e poi scaricata per sempre nel vuoto . Ciò significa che la dichiarazione di funzione o metodo non rimane in memoria.
void
prima. Mi piace.
Prima devi visitare MDN IIFE , ora alcuni punti a riguardo
Sembra che a questa domanda sia stata data una risposta pronta, ma posterò comunque il mio contributo.
So quando mi piace usare le funzioni di auto-esecuzione.
var myObject = {
childObject: new function(){
// bunch of code
},
objVar1: <value>,
objVar2: <value>
}
La funzione mi consente di utilizzare un codice aggiuntivo per definire gli attributi e le proprietà childObjects per un codice più pulito, come l'impostazione di variabili comunemente utilizzate o l'esecuzione di equazioni matematiche; Oh! o controllo degli errori. anziché essere limitato alla sintassi di istanza di oggetti nidificati di ...
object: {
childObject: {
childObject: {<value>, <value>, <value>}
},
objVar1: <value>,
objVar2: <value>
}
La codifica in generale ha molti modi oscuri di fare molte delle stesse cose, facendoti chiederti: "Perché preoccuparsi?" Ma continuano a comparire nuove situazioni in cui non puoi più fare affidamento solo sui principi di base / core.
Data la tua semplice domanda: "In javascript, quando vorresti usare questo: ..."
Mi piacciono le risposte di @ken_browning e @ sean_holding, ma ecco un altro caso d'uso che non vedo menzionato:
let red_tree = new Node(10);
(async function () {
for (let i = 0; i < 1000; i++) {
await red_tree.insert(i);
}
})();
console.log('----->red_tree.printInOrder():', red_tree.printInOrder());
dove Node.insert è un'azione asincrona.
Non posso semplicemente chiamare wait in attesa senza la parola chiave asincrona alla dichiarazione della mia funzione e non ho bisogno di una funzione con nome per un uso successivo, ma devo attendere quella chiamata insert o ho bisogno di altre funzionalità più ricche (chi lo sa?) .
IIRC ti consente di creare proprietà e metodi privati.