2012-06-25 28 views
16

In this commit v'è un cambiamento non riesco a spiegareUnderstanding "questa" parola chiave

deferred.done.apply(deferred, arguments).fail.apply(deferred, arguments); 

diventa

deferred.done(arguments).fail(arguments); 

AFAIK, quando si richiama una funzione come un membro di qualche oggetto come obj.func(), all'interno della funzione this è associato a obj, quindi non ci sarebbe alcun modo di invocare una funzione tramite apply() solo per il numero a obj. Invece, secondo i commenti, questo era necessario a causa di alcune precedenti implementazione $.Callbacks.add.

Il mio dubbio non si tratta di jQuery, ma circa il linguaggio Javascript stesso: quando si richiama una funzione come obj.func(), come può essere che all'interno func() la parola this non è vincolata-obj?

+1

In che modo la modifica del commit è correlata alla tua domanda? '.apply' è stato usato per passare la quantità' n' di argomenti ad un'altra funzione, non per il suo contesto che costringe le abilità. – Esailija

+0

@Esailija, penso che tu abbia capito il punto! – Raffaele

+0

@Christoph Penso che abbia capito il punto. apply() non è stato usato per forzare il contesto, poiché * questo * era già * posizionato correttamente * (e questo risponde alla mia domanda) – Raffaele

risposta

5

Il mio dubbio non si tratta di jQuery, ma circa il linguaggio Javascript stesso: quando si richiama una funzione come obj.func(), come può essere che all'interno func() la parola chiave this non è tenuto a obj?

Ebbene, l'unico modo in cui questo è possibile è se obj.func riferimento a una funzione bound, allora non importa come si chiama. In tal caso, non importa come si chiama la funzione, se si fa obj.func(), func(), func.call({}), func.apply({}) non importa affatto. Non sono sicuro di come il commit sia collegato a questo, comunque.

Per chiarire, sto rispondendo alla domanda citato interpretato come:

dato una firma chiamata come: obj.func(), come è possibile che this è nonobj all'interno della funzione chiamata per la chiamata?

+0

Ottima risposta. Mi chiedo se hai appena indovinato o se sapessi che $ .Callbacks.add non può gestire gli argomenti passati come un array come :) – Raffaele

+0

@Raffaele In effetti, nessuno dei due. È solo che '.apply (something, arguments)' è l'unico modo per passare argomenti esattamente come sono stati passati alla funzione chiamante. Bene, suppongo che si possa fare qualcosa con 'eval' ma questo non conta: D – Esailija

+0

Questo è ancora maggiore :) Quindi la chiave è stata ti ha riconosciuto gli argomenti ** ** di parole chiave nel costrutto * .Applicare (smth, argomenti * * e collegato immediatamente a chiamate concatenate. Spesso per risolvere problemi complessi è necessaria una profonda conoscenza del soggetto (esperienza) e * pensiero laterale * :) – Raffaele

2

Ciò è possibile solo facendo riferimento alla funzione da un altro oggetto in questo modo

obj2.func = obj.func; 
obj2.func(); // 'this' now refers to obj2 

var func2 = obj.func; 
func2(); // 'this' now refers to the global window object 

o chiamando .Applicare() o .Call() per associare this a qualsiasi oggetto arbitrario.

+0

Questo è giusto, ma non risponde alla mia domanda :) Volevo sapere la differenza, per quanto riguarda ** questo ** delimitazione, tra * ab (args) * e * abbozzo (b, args) * Vedi @ Risposta wnwall – Raffaele

+0

I * ha * risposto alla tua domanda: "quando invochi una funzione come obj.func(), come può essere che all'interno func() la parola chiave non sia associata a obj?" :-) Quello che affermi come la tua domanda non è nel primo post: forse dovresti aggiornarlo! –

+0

Io non la penso così: P In realtà, il tuo esempio non chiama mai * func * come membro di * obj *: succede a invocare lo stesso oggetto funzione, ma come proprietà di un altro oggetto (o * obj2 * o * finestra*). Quindi il valore di * this * è prevedibile e previsto. Invece, ho chiesto se quando il motore esegue * a.b() * c'è qualche possibilità che, dentro * b() *, * questo!= a *. – Raffaele

1

Una funzione viene sempre chiamata con un ricevitore, chiamato this all'interno della funzione, che viene dato in chiamata.

Quando stai scrivendo

obj.someFunc = function() {... 

che non stai dicendo che somefunc deve avere come ricevitore obj, si sta solo dicendo che obj ha una proprietà chiamata somefunc il cui valore è una funzione.

Se fai

var aFunc = obj.someFunc; 

piace è fatto in molti luoghi (fa riferimento di callback per esempio) e dopo che

aFunc(); 

il ricevitore (this) è in questo caso la finestra.

Questo perché le funzioni, in javascript, contrariamente ai linguaggi come java, sono oggetti di "prima classe", il che significa in particolare che è possibile passarli come valori e non essere associati a un ricevitore prespecificato univoco.

+0

Vedere @Esailija e le risposte. Quello che hai detto è corretto, ma non affronta la questione, dal momento che esplicitamente legato il codice sorgente e la funzione è davvero definitivamente come obj.func() – Raffaele

+0

Grazie per si commento indicando la risposta di Esailija. Hai perfettamente ragione. –

1

La versione abbreviata che utilizzo è che this in JavaScript fa sempre riferimento all'oggetto di cui la funzione attualmente in esecuzione è un metodo - tranne nel caso particolare quando il metodo è un callback, quando this fa riferimento all'oggetto a cui la callback è vincolata (es. un pulsante).

Modifica: nota che una funzione globale è come un metodo dell'oggetto window.

This QuirksMode page mi ha aiutato quando stavo imparando a riguardo.

5

Mentre le altre risposte riguardano la domanda relativa alla parola chiave this, non rispondono alla domanda relativa al motivo per cui è in uso lo apply. Ecco il kicker: apply non viene utilizzato per impostare la parola chiave this in questo esempio. Invece, viene utilizzato per passare arguments come argomenti delle funzioni done e fail.

Prendete questo esempio:

var x = { 
    a: function(a1, a2, a3) { 
     console.log(a1, a2, a3); 
    } 
} 

function callA() { 
    x.a.apply(x, arguments); 
    x.a(arguments); 
} 

callA('red', 'blue', 'green'); 

Se si esegue questo codice si dovrebbe vedere la differenza tra x.a.apply(x, arguments); e x.a(arguments);. Nel primo, a1, a2 e a3 i rispettivi colori "rosso", "blu" e "verde". Nella seconda, a1 è un oggetto di tipo array [ "red", "blue", "green" ] e a2 e a3 sono undefined.

Allo stesso modo, nell'esempio pubblicato, apply viene utilizzato per passare correttamente l'oggetto arguments, non per impostare la parola chiave this.

+0

+1, scusate questo non può essere accettato, ma Esailija è il primo (più ha menzionato gli oggetti legati). Tuttavia apprezzo molto la chiarezza e spero che il tuo codice di esempio possa aiutare gli altri a capire la vera domanda come hai fatto tu :) – Raffaele