2010-07-23 4 views
14

io sono un principiante di chiusure (e javscript in generale), e non riesco a trovare una spiegazione soddisfacente per quello che sta succedendo in questo codice:Perché questa chiusura non ha accesso alla parola chiave "this"? - jQuery

function myObject(){ 
    this.myHello = "hello"; 
    this.myMethod = do_stuff; 
} 

function do_stuff(){ 
    var myThis = this; 
    $.get('http://example.com', function(){ 
     alert(this.myHello); 
     alert(myThis.myHello); 
    }); 
} 

var obj = new myObject; 
obj.myMethod(); 

avviserà 'undefined' e poi 'ciao'. Ovviamente questo non dovrebbe essere jQuery specifico, ma questa è la forma più semplice del mio codice originale che potrei inventare. La chiusura in do_stuff() ha accesso alle variabili in tale ambito, ma a quanto pare questa regola non si applica alla parola chiave this.

Domande:

Cosa succede al this quando la chiusura è passato al di fuori del campo di applicazione del do_stuff() (in questo caso $.get())? myThis contiene una copia di this o un riferimento ad esso? Non è generalmente una buona idea usare this nelle chiusure?

Qualsiasi risposta molto apprezzata.

risposta

8

Cosa succede quando la chiusura viene superata dall'ambito di do_stuff() (in questo caso $ .get())?

Ogni funzione ha un proprio contesto di esecuzione, la parola chiave this recupera il valore del contesto corrente.

Il doStuff identificativo e la proprietà obj.myMethod si riferiscono allo stesso oggetto funzione, ma dal momento che si invoca come una proprietà di un oggetto (obj.myMethod();), il valore this dentro quella funzione, si riferirà a obj.

Quando la richiesta Ajax è riuscita, jQuery invocherà la seconda funzione (iniziando un nuovo contesto di esecuzione) e utilizzerà un oggetto che contiene le impostazioni utilizzate per la richiesta come valore this di quella richiamata.

MyThis contiene una copia di questo o un riferimento ad esso?

L'identificatore myThis conterrà un riferimento all'oggetto che viene fatto riferimento anche dal valore this sulla portata esterna.

Non è generalmente una buona idea usare questo in chiusure?

Se si capisce come il valore this sia gestito in modo implicito, non vedo alcun problema ...

Dal momento che si sta utilizzando jQuery, si potrebbe desiderare di controllare il metodo jQuery.proxy, è un metodo di utilità che può essere utilizzato per conservare il contesto di una funzione, ad esempio:

function myObject(){ 
    this.myHello = "hello"; 
    this.myMethod = do_stuff; 
} 

function do_stuff(){ 
    $.get('http://example.com', jQuery.proxy(function(){ 
     alert(this.myHello); 
    }, this)); // we are binding the outer this value as the this value inside 
} 

var obj = new myObject; 
obj.myMethod(); 

Vedi anche:

+0

Stavo per chiedere un seguito ma la tua ultima modifica ha risposto. Grazie! – thewiglaf

+0

@thewiglaf: Prego! Sentiti libero di commentare se hai dei dubbi ... – CMS

2
$.get('http://example.com', function(){ 
    alert(this.myHello); // this is scoped to the function 
    alert(myThis.myHello); // myThis is 'closed-in'; defined outside 
}); 

notare la funzione anonima. questo in questo ambito è lo scopo della funzione. myThis è l'ambito esterno, in cui è stato definito myHello. Controllalo in Firebug.

'questo' sempre si riferisce allo scopo corrente di esecuzione, credo. Se vuoi prendere l'ambito attuale e conservarlo, fai ciò che hai fatto, che è assegnato a un'altra variabile.

1
$.get('http://example.com', function(){ 
    // inside jQuery ajax functions - this == the options used for the ajax call 
}); 

Cosa succede quando la chiusura viene superata dall'ambito di do_stuff() (in questo caso $ .get())?

Nothing "accade" ad esso, questo è ancora questo per quella di chiusura, il contesto di esecuzione delle funzioni chiamate dalla chiusura non ereditano automaticamente this.

MyThis contiene una copia di questo o un riferimento ad esso?

Tutte le assegnazioni non scalari sono riferimenti in JavaScript. Quindi è un riferimento a this, se si modificano le proprietà su entrambi, cambiano per entrambi.

Non è generalmente una buona idea usare questo in chiusure?

è generalmente una buona idea di utilizzare this nelle chiusure, ma se avete intenzione di utilizzare le chiusure all'interno che hanno bisogno di accedere alla stessa this, la sua buona pratica di fare esattamente quello che hai fatto: var someName = this; e poi accesso usando someName