2010-11-18 14 views
53

Vedo spesso il seguente codice:funzione init in javascript e come funziona

(function() { 
    // init part 
})(); 

ma non ho mai potuto ottenere la mia testa intorno come funziona. Trovo le ultime parentesi particolarmente confuse. Qualcuno potrebbe spiegare come funziona in termini di contesti di esecuzione (EC) e oggetti variabili (VO)?

+2

sei interessato a una "spiegazione formale", in termini di specifiche ECMA-262? – CMS

+1

Leggi informazioni sullo [scopo di questo costrutto] (http://stackoverflow.com/q/592396/1048572). Dai un'occhiata a una spiegazione [tecnica] non tecnica (http://stackoverflow.com/q/8228281/1048572), anche [qui] (http://stackoverflow.com/a/441498/1048572). Per la sintassi, vedere [perché le parentesi sono necessarie] (http://stackoverflow.com/q/1634268/1048572) e [dove dovrebbero andare] (http://stackoverflow.com/q/3384504/1048572) . – Bergi

risposta

46

Quel modello creerà un nuovo contesto di esecuzione (EC) in cui tutti gli oggetti variabili locali (VO) vivranno e morirà allo stesso modo quando si esce dall'EC. L'unica eccezione a questa vita è per i VO che diventano parte di uno closure.

Si noti che JavaScript non ha la funzione "init" magica. È possibile associare questo modello a un tale dato che la maggior parte di qualsiasi libreria JS che si rispetti (jQuery, YUI, ecc.) Farà ciò in modo che non inquinino il NS globale più del necessario.

A dimostrazione:

var x = 1; // global VO 
(function(){   
    var x = 2; // local VO 
})(); 
x == 1; // global VO, unchanged by the local VO 

La 2a serie di "staffe" (quelli sono effettivamente chiamati parentesi, o un insieme di parentesi), sono semplicemente per richiamare l'espressione funzione direttamente precedente (come definito dalla insieme precedente di parentesi).

+7

Ora, se hai spiegato che EC e VO erano per sviluppatori che non capiscono, ti avrei dato un voto ascendente, ma invece di una risposta completa, potrebbe essere per gli acronimi di Google. –

+14

Non ho definito EC e VO perché la domanda originale conteneva definizioni per questi, quindi se leggi la domanda dovresti già sapere cosa significano;) Inoltre, queste 2 pagine potrebbero aiutarti a capire meglio le EC/VO (variabili) : 1. http://jibbering.com/faq/ 2. http://jibbering.com/faq/notes/closures/ – ken

+0

@ken grazie per i link – Chris22

26

Il codice crea una funzione anonima e quindi la esegue immediatamente. Simile a:

Lo scopo di questa costruzione è creare un ambito per il codice all'interno della funzione. È possibile dichiarare varaibles e funzioni all'interno dell'ambito e quelli saranno locali a tale scopo. In questo modo non ingombrano l'ambito globale, riducendo al minimo il rischio di conflitti con altri script.

+0

Rispettosamente, per quelli di voi che continuano a invitare questa risposta, la soluzione data non risponde a nessuna delle domande che l'OP ha richiesto * a tutti *. Chiede informazioni sull'ultimo set di parentesi [sic] e su come il codice dato si riferisce a EC e VO ... ciò che è stato fornito da Guffa assomiglia alla risposta anonima della funzione run-of-the-mill che non affronta i punti specifici l'OP fa apparire. – ken

+3

@ken: alla gente sembra piacere come spieghi cosa fa il codice e perché viene usato. Solo perché non uso i termini esatti che fai, non lo rende sbagliato. – Guffa

+0

Non ho mai detto che fosse/sbagliato /, stavo solo sottolineando che la tua risposta alla copia/incolla non tiene conto di ciò che l'OP ha chiesto, tutto qui. – ken

78

Il modo in cui solitamente lo spiego alle persone è mostrare come è simile ad altri pattern JavaScript.

In primo luogo, si dovrebbe sapere che ci sono due modi per dichiarare una funzione (in realtà, c'è almeno cinque, ma questi sono i due principali colpevoli):

function foo() {/*code*/}

e

var foo = function() {/*code*/};

Anche se questa costruzione sembra strana, probabilmente la si utilizza sempre durante il collegamento di eventi:

Si dovrebbe notare che la seconda forma non è molto diverso da una dichiarazione di variabile normale:

var bar = 5; 
var baz = 'some string'; 
var foo = function() {/*code*/}; 

Ma in JavaScript, si ha sempre la scelta tra l'utilizzo direttamente o tramite una variabile un valore. Se bar è 5, quindi i prossimi due dichiarazioni sono equivalenti:

var myVal = bar * 100; // use 'bar' 
var myVal = 5 * 100; // don't use 'bar' 

Beh, se è possibile utilizzare 5 da solo, perché non si può utilizzare function() {\*code*\} da solo troppo? In effetti, puoi. E questa è chiamata funzione anonima.Quindi questi due esempi sono ugualmente uguali:

var foo = function() {/*code*/}; // use 'foo' 
foo();       

(function(){/*code*/}());  // don't use 'foo' 

L'unica differenza che dovresti vedere è nelle parentesi aggiuntive. Questo è semplicemente perché se si avvia una linea con la parola chiave function, il parser penserà che si sta dichiarando una funzione utilizzando il primo modello all'inizio di questa risposta e si genera un'eccezione di errore di sintassi. Quindi avvolgi tutta la tua funzione anonima all'interno di un paio di parentesi graffe e il problema scompare.

In altre parole, le seguenti tre affermazioni sono valide:

5;      // pointless and stupid 
'some string';   // pointless and stupid 
(function(){/*code*/}()); // wonderfully powerful 
+2

"Il modo in cui solitamente lo spiego alle persone è mostrare come è simile ad altri pattern JavaScript. " È stato incredibilmente utile, quindi grazie per aver dedicato del tempo e facendolo :) – NessDan

+0

Penso che tu abbia digitato (function() {/ * code * /}()); intendevi digitare (function() {/ * code * /})() ;. Corretta? – RayLoveless

+0

No, ma non importa. Douglas Crockford raccomanda il modulo che ho usato, mentre molte persone raccomandano il tuo. Vedi http://stackoverflow.com/questions/3783007/is-there-a-difference-between-function-and-function. In realtà, la ragione per Parens è che stai cercando di evitare di iniziare l'istruzione con 'function' (quindi potresti anche fare facilmente'! Function() {/ * code * /}() 'o' -function () {/ * code * /}() '. Non mi piace tutto ciò che Crockford consiglia, ma penso che la sua rigorosa coerenza sia migliore dell'alternativa di tutti-fai-cosa-vuoi e del suo strumento di sfilacciatura (JSLint) – Andrew

14

Non posso credere che nessuno ha risposto alla domanda ops!

L'ultimo set di parentesi è utilizzato per passare i parametri alla funzione anonima. Così, l'esempio seguente crea una funzione, poi corre con la x = 5 e y = 8

(function(x,y){ 
    //code here 
})(5,8) 

Questo può sembrare non così utile, ma ha il suo posto. Il più comune che ho visto è

(function($){ 
    //code here 
})(jQuery) 

che permette di jQuery per essere in modalità compatibile, ma è possibile fare riferimento ad esso come "$" all'interno della funzione anonima.

+1

Ciò può anche migliorare le prestazioni abbreviando la [catena di ambito] (http://jibbering.com/faq/notes/closures/) per quella particolare variabile. – ken

1

In parole semplici si può capire che ogni volta che il caricamento della pagina, da questa seconda coppia di parentesi() la funzione sarà chiamato default.We non deve chiamare il function.It è nota come funzione anonima.

cioè

(function(a,b){ 
//Do your code here 
})(1,2); 

Si stessa come come

var test = function(x,y) { 
    // Do your code here 
} 
test(1,2); 
1

sua è chiamato immediatamente richiamando espressione di funzione (IIFE). Principalmente associato al concetto di chiusura di JavaScript. L'utilizzo principale è quello di eseguire la funzione prima che la variabile globale sia modificata, in modo che il comportamento previsto del codice possa essere mantenuto.

+0

E qui c'è un link: https://en.wikipedia.org/wiki/Immediately-invoked_function_expression – Luke

Problemi correlati