2012-01-04 14 views
8

Sono nuovo di JavaScript, e sto avendo un problema comprensione di questo codice:Incomprensione di JavaScript chiusure

function addProperty(o) { 
    var value; 

    o["get"] = function() { return value; } 
    o["set"] = function(v) { value = v; } 
} 

var a = {}; 
addProperty(a); 
var b = {}; 
addProperty(b); 

a.set(4); 
b.set(5); 
print("a is " + a.get() + "; b is " + b.get()); 

Questo stampa (in v8/D8) a is 4; b is 5. Se commento la riga var value;, ottengo a is 5; b is 5. Dov'è l'oggetto 'valore', e perché ci sono due di questi? Grazie.

+0

Non capisco il "perché ce ne sono due "parte della domanda. Potresti per favore chiarire? – slinzerthegod

+0

L'oggetto 'a' ha un valore associato ad esso, che contiene un intero '4', e l'oggetto 'b' ha un valore associato ad esso, che contiene un intero '5'. – EML

risposta

12

La variabile value è locale a addProperty. La prima volta che viene chiamato addProperty, viene creato un nuovo value, su cui si chiudono entrambe le funzioni. Viene chiamata la seconda volta addProperty, viene creato un secondo value su cui si chiudono due nuove funzioni.

Rimozione var crea un globalevalue sull'oggetto window che è condivisa da tutte le funzioni.

Forse hai intenzione di fare questo:

function createPropertyMgr() { 
    var value; 
    return function(o) { 
     o["get"] = function() { return value; } 
     o["set"] = function(v) { value = v; } 
    } 
} 

var addProperty = createPropertyMgr(); 

Questa nuova funzione addProperty chiude più di un value non importa quante volte si chiama. Non sono sicuro di aver compreso il caso d'uso, ma questo dovrebbe dimostrare la differenza.

+4

+1 C'è un "valore" in * origine *, ma due in * memoria *. Questa sembra essere la confusione dell'OP. – pimvdb

+0

Quindi, crea una copia del valore var su ogni chiamata addProperty. Ma come lo lega all'argomento oggetto? –

+1

@TomasNarros: allo stesso modo. Parametri formali, dichiarazioni di funzioni e variabili dichiarate con 'var' fanno tutti parte dell '" Oggetto di attivazione "e cioè, che viene copiato per creare una chiusura lessicale. – jAndy

1

Quando non si dichiara esplicitamente una variabile all'interno di una funzione, il suo ambito viene assunto come globale. Nel secondo caso, poiché non hai dichiarato esplicitamente come value come locale nella funzione addProperty(), viene trattato come globale.

Ma quando lo si dichiara esplicitamente all'interno di una funzione, diventa locale alla funzione. Ogni volta che la funzione viene invocata, una nuova copia della variabile locale della funzione viene creata nello stack (e, soprattutto, rimane nello stack finché c'è un riferimento)