2012-04-12 10 views
7

Questi sono presi dai tutor di Jquery tutor-tuts premium.
http://tutsplus.com/lesson/the-this-keyword/ Jeff spiega a cosa si riferisce ogni volta, ma non sono sicuro di aver afferrato il ragionamento che sta dietro a tutti.4 diversi scenari di "questo". Qual è l'interpretazione corretta?

E.g. 1

function doSomething(e) { 
e.preventDefault(); 
console.log(this); 
} 

$('a').on('click', doSomething); 

In questo caso "questo si riferisce alla 'un' elemento" (essendo in questo caso l'oggetto padre)

Credo che sia perché qui la dichiarazione equivale a:

$('a').on('click', function (e) { 
    e.preventDefault(); 
    console.log(this); 
    } 

Quindi 'a' è l'oggetto padre

Es. 2

var obj = { 
    doIt: function(e){ 
    e.preventDefault(); 
    console.log(this); 
    } 
} 

$('a').on('click', obj.doIt); 

In questo caso "questo si riferisce ancora al 'un' elemento" (* ma a quanto pare non è l'oggetto padre?)

Sembra che questa volta stiamo chiamando un metodo, ma la la dichiarazione equivale ancora alla stessa cosa di Eg 1

* Una cosa nel tutorial mi ha un po 'confuso. Pensavo che "questo" si riferisse sempre all'oggetto genitore, quindi in questo caso "a" è ancora l'oggetto genitore. Ma (alle 5.23 del tutorial) deduce che non è il caso, affermando "ci possono essere delle volte in cui si desidera che" questo "si riferisca al suo oggetto genitore che sarebbe" obj "" nel qual caso crea a.g.g.3.

E.g. 3

var obj = { 
    doIt: function(){ 
    console.log(this); 
    } 
} 

$('a').on('click', function(e){  
obj.doIt(); 
     }; 
e.preventDefault(); 

In questo caso "Questo fa riferimento all'oggetto obj"

presumo questo per il fatto che 'questo' è una funzione nidificata come questa affermazione equivale a:

$('a').on('click', function(){  
function(){ console.log(this);} 
}; 
e.preventDefault(); 

In realtà non capisco perché, soprattutto perché ho letto in un articolo che nelle funzioni annidate "questo" "perde la sua strada e si riferisce all'oggetto principale (oggetto finestra)".

EG4

var obj = { 
    doIt: function(){ 
    console.log(this);  
    } 
} 

$('a').on('click', function(e){  
     obj.doIt.call(this);    
     e.preventDefault(); 
}); 

In questo caso "Questo si riferisce al 'un'"

Secondo JavaScript Definitive Guide "Il primo argomento sia chiamata() è l'oggetto su cui la funzione deve essere invocata " Qui" questo "è l'usato come primo argomento. Ma "questo" non è l'oggetto su cui la funzione deve essere invocata ??
Penso di ottenere che la funzione di chiamata sia lì per richiamare la funzione e utilizzare il suo primo parametro come puntatore a un oggetto diverso, ma non capisco perché usare "questo" significa che la funzione è invocata da "a". Non è qualcosa che ho visto in altri esempi call().

Scusate per un post così mastodontico.Spero che qualcuno stia ancora leggendo in questa fase ...

+0

+1 perché è troppo tardi qui per me iniziare rispondere a questa eccellente domanda. Non c'è dubbio che presto arriverà qualcun altro - è un punto vitale ed è generalmente trattato male nei tutorial di JS. – jimw

+3

* "Ho pensato 'questo' si riferisce sempre all'oggetto genitore ..." * No, non pensare a 'this' come l'oggetto genitore. Consideralo come un * contesto di chiamata * il cui valore può essere impostato in diversi modi, uno dei quali è la chiamata a un metodo da un oggetto. –

risposta

4

Spero che questo aiuti a chiarire il problema, può essere davvero fonte di confusione.

  • Quando this è sciolto sul vostro codice, si farà riferimento all'oggetto globale (nei browser web, che è window).

    console.log(this); // window 
    
  • Quando this è all'interno di un metodo di oggetto (come sul Ad es 3), si farà riferimento all'oggetto. Questo si applica agli oggetti istanziati con new o come valori letterali oggetto (come nell'esempio).

    var obj = { 
        doIt: function(e){ 
         console.log(this); 
        } 
    } 
    obj.doIt(); // obj 
    
  • All'interno di un gestore di eventi, this farà riferimento all'oggetto l'evento è destinato a.

    // This is the plain js equivalent of your jQuery example 
    document.getElementsByTagName['a'][0].addEventListener('click', function(e){ 
        console.log(this); // the first anchor on the document 
    }); 
    
    // This is exactly the same: 
    var clickHandler = function(e){ 
        console.log(this); // the first anchor on the document 
    }; 
    document.getElementsByTagName['a'][0].addEventListener('click', clickHandler); 
    
    // Even if the handler is defined inside of another object, this will be 
    // the obj the event is bound to. It's the case of your E.g. 2 
    var obj = { 
        doIt: function(e){ 
         console.log(this); // the first anchor on the document 
        } 
    } 
    document.getElementsByTagName['a'][0].addEventListener('click', obj.doIt); 
    // When you pass obj.doIt to addEventListener above, you are passing a reference 
    // to that function. It's like "stealing" the function from the object 
    
  • Quando un oggetto viene passato come primo parametro per Function.call o Function.apply, se this appare all'interno della funzione si farà riferimento all'oggetto che avete passato. È un modo per forzare ciò a cui punta this.

    var obj = { 
        doIt: function(){ 
         console.log(this); // window 
        } 
    } 
    obj.doIt.call(window); 
    
+0

Tuttavia, dato 'obj' con una funzione' doIt', se facciamo 'var fn = obj.doIt; fn() ',' this' farà riferimento a 'window' all'interno di' fn'. –

+0

Sì, proprio come nel mio esempio con 'addEventListener' (eccetto che in quel caso punta a un nodo DOM, non a' window'). Ma la logica è la stessa. – bfavaretto

0

Il modo in cui si comporta this in JavaScript è un po 'confuso all'inizio. Fondamentalmente, a differenza delle variabili (che sono sottoposte a revisione statica), this è dinamicamente con ambito. Cioè, il valore di this è determinato da dove si chiama la funzione anziché da dove l'hai scritta.

Quando si passa la funzione a on, in seguito viene chiamato da un contesto in cui this è l'elemento in questione. Questo succede indipendentemente da di come hai ottenuto quella funzione. Vale a dire, a una funzione non importa se l'accesso avviene tramite la sintassi come obj.fn o semplicemente il suo nome fn - il valore dell'espressione è lo stesso in entrambi i casi.

Con cose diverse dalle funzioni, questo ha senso. Dato:

var a = 10, 
    obj = { a : 10 }; 

che sarete d'accordo che le espressioni a e obj.a hanno lo stesso valore. Questo vale anche per le funzioni.

In breve: il valore di this dipende da dove e come si chiama la funzione anziché come e dove l'hai dichiarata o come ci si è riferiti prima di chiamarla.

+3

Non dovremmo confondere 'this' con" scope ". Sono completamente separati. E "questo" non è determinato da * dove *, ma piuttosto da * come * viene chiamata la funzione. –

+0

Dando un'occhiata più da vicino, ci sono diverse cose sbagliate. Come ... * "... in seguito viene chiamato da un contesto in cui questo è l'elemento in questione" *. Questo non fa differenza. Non vi è alcun trasferimento del contesto di inclusione a quello invocato a meno che non lo trasferiate manualmente usando '.call()' o '.apply()'. E questo ... * "... a una funzione non importa se accedete usando la sintassi come' obj.fn' o solo il suo nome 'fn'" * ... non è giusto neanche. Fa davvero la differenza. –

+0

Il mio punto era che l'espressione 'f' e' obj.f' hanno lo stesso valore (a patto che 'f' e' obj.f' puntino alla stessa funzione). Forse non ero abbastanza chiaro su questo. Per quanto riguarda l'altro punto, puoi cambiare il valore di 'this' senza' call' o 'apply' inserendo la funzione nell'oggetto. Quindi, se * lo chiami * da un oggetto o di per sé è importante, ma per accedervi (ottenere la funzione come valore) non ha importanza. –

0

davvero apprezzare queste risposte ragazzi. Ho pubblicato nelle prime ore e ho provato (necessario) a prendere un po 'di tempo per digerire il tuo feedback.

https://developer.mozilla.org/en/JavaScript/Reference/Operators/this è stato un grande urlo. Ho letto pochissimi articoli/tut e questo sembra uno dei migliori.

Penso che l'illuminazione principale sia stata che l'oggetto associato a "questo" è determinato da come/dove è stata chiamata la funzione (contesto di chiamata) piuttosto che da come o dove è stata definita la funzione.

Quindi, solo per tornare le cose al Q & A portata e tentare di rispondere alla mia Q alla luce di quanto voi ragazzi avete risposto ...

Ad es 1 Qui: la funzione 'doSomething' stato chiamato nel contesto del gestore click in modo da l'oggetto legato a 'questo' è "A"

Ad es 2 Anche in questo caso il gestore di clic è ancora innescare la funzione in modo da l'oggetto legato a 'questo' è "un"

Ad es 3 Nella funzione nidificata il contesto di chiamata è obj.doIt(). Quindi, come dice nel tutorial, l'oggetto associato a "this" è "obj".

Sebbene, basato sulla logica simile da developer.mozilla.org esempio sotto, non è l'oggetto realmente legata a "obj.doIt":

o.b = {g: independent, prop: 42};   
console.log(o.b.g()); // logs 42   

"il questa associazione è influenzato solo dai più riferimento immediato ai membri ... questo all'interno della funzione si riferirà a ob. Il fatto che l'oggetto stesso sia un membro di o non ha alcuna conseguenza, il riferimento più immediato è tutto ciò che conta. "

E.g. 4

Qui - il lavoro di 'chiamata' è di invocare indirettamente la funzione come se fosse un metodo di un nuovo oggetto - in questo caso abbiamo definito 'questo'. Qui "this" si riferisce a "a" poiché fa parte della funzione innescata dal gestore di clic

Spero che questo sia un po 'più vicino. Mi sento un idiota su questo (gioco di parole intenzionale) perché le risposte sono presentato a me ancora non sono ancora del tutto sicuro che sto inchiodare il concetto.

Se devo strisciare di nuovo al mio foro per un po 'per digerire mi dichiaro lo stato newby, incidente scorre Javascript JQuery & solo per un poche settimane.

nuovo

Grazie per l'ognuno di feedback.

Problemi correlati