2009-03-10 7 views
13

Sto cercando di avvolgere la mia testa intorno chiusure (c'è una barzelletta lì da qualche parte) e mi sono imbattuto in questo:ambito Javascript e chiusura

(function() { /* do cool stuff */ })(); 

Come funziona? Qual è lo scopo di mettere la funzione in parens? Perché i parens vuoti in seguito?

risposta

30

Il punto è che tutte le variabili dichiarate nelle cose interessanti non verranno create nello spazio dei nomi globale. Qualsiasi funzione in javascript creerà un tale ambito. Supponiamo di avere qualche javascript che vuoi eseguire. Se si esegue questa operazione:

var b = 1; 
// stuff using b 

E qualche altro codice utilizza b, che avrà il suo valore di sinistra sopra. (O, peggio ancora, se qualche altro codice imposta b prima dell'esecuzione del codice, quindi cerca di ottenere il suo vecchio valore in seguito, lo avresti cambiato nel frattempo.)

D'altra parte, se si dispone di questo codice, che dichiara e poi chiama la funzione:

function a() { 
    var b = 1; 
} 

a(); 

e qualche altro codice utilizza in seguito b, non vedrà i propri valori, in quanto b è locale alla funzione. Il problema con questo, ovviamente, è che stai ancora facendo un nome globale - "a", in questo caso. Quindi, vogliamo una funzione senza nome: ecco perché ottieni il codice che hai descritto. Dichiara una funzione senza nome e quindi la chiama.

Purtroppo, non si può solo dire:

function() { ... }() 

perché questo sarà analizzato come una dichiarazione di funzione dichiarazione, e poi un errore di sintassi. Inserendo la dichiarazione della funzione tra parentesi, si ottiene una funzione espressione, che può quindi essere richiamata. Lo chiami come qualsiasi altra espressione di funzione (come a, sopra), usando il secondo set di parents. Ad esempio, se la funzione ha assunto argomenti, li passeresti lì:

(function(a) { ... })(1) 
0

Questo costrutto significa dichiarare una funzione anonima ed eseguirlo immediatamente. Il motivo per cui inserisci il tuo codice all'interno di un corpo di una funzione è perché le variabili che hai definito al suo interno rimangono locali alla funzione e non come variabili globali. Tuttavia, saranno comunque visibili alle chiusure definite all'interno di questa funzione.

1

I parenti attorno alla funzione chiariscono che la funzione è un'espressione. I parenti dopo sono la chiamata alla funzione.

Si noti che la funzione non ha un nome.

6

Questo crea una funzione, la chiama e la elimina.

Potrebbe essere più chiaro se si guarda in questo modo:

var throwaway = function(){ 
    // do cool stuff 
}; 
throwaway(); 

Questo viene fatto per creare uno spazio dei nomi privato. Il codice nella funzione può avere funzioni e variabili senza preoccuparsi del conflitto con altri codici caricati nella pagina.

+3

Tranne, ovviamente, che sia in conflitto con il nome della vostra funzione. –

+2

Uh, si. Ecco perché è normalmente fatto con una funzione anonima. Ho appena usato una funzione con nome per mostrare una forma più familiare che fa la stessa cosa. –

+0

jder ha la risposta migliore, per quelli che arrivano in ritardo alla festa. – Triptych

0

Inserire la dichiarazione di funzione all'interno di Paren crea un'espressione che valuta la funzione anonima all'interno. Pertanto, il primo parentetico valuta una funzione.

I "parenti vuoti" alla fine richiamano la funzione definita, quindi "// fa cose interessanti" viene eseguito immediatamente.

Questo è un modo per eseguire il codice al volo mantenendo anche le variabili fuori dall'ambito globale.

Ciò che è illustrato qui, tuttavia, non ha nulla a che fare con chiusure - almeno non direttamente. Le chiusure riguardano il mantenimento di uno scope lessicale dopo che una funzione genitore è già uscita.

2

ho appena trovato questo post di recente. Questo tipo di chiamata di funzione chiamata & si chiama funzioni di autoinvocazione.

(function(){ //code })(); 

Il codice all'interno della funzione sarà eseguito immediatamente dopo la sua definizione.

1

Un approccio chiusure è quello di passare le variabili alla funzione:

(function($, var_1, var_2) { 
    // use JQuery, var_1 and var_2 as local variables 
})($, var_1, var_2);