2011-09-18 19 views
15

Stavo navigando attraverso lo JavaScript Garden quando mi sono imbattuto nel trucco Function.call.apply che viene utilizzato per creare "wrapper veloci e non associati". Dice:Qual è lo scopo dell'uso di Function.call.apply in JavaScript?

Un altro trucco consiste nell'utilizzare entrambe le chiamate e applicare insieme per creare wrapper veloci e non associati.

function Foo() {} 

Foo.prototype.method = function(a, b, c) { 
    console.log(this, a, b, c); 
}; 

// Create an unbound version of "method" 
// It takes the parameters: this, arg1, arg2...argN 
Foo.method = function() { 

    // Result: Foo.prototype.method.call(this, arg1, arg2... argN) 
    Function.call.apply(Foo.prototype.method, arguments); 
}; 

Quello che non capisco è perché preoccuparsi utilizzando Function.call.apply quando Function.apply sarebbe sufficiente. Dopo tutto, entrambi sono semanticamente equivalenti.

+0

Ho inserito un collegamento al [JavaScript Garden] (http://javascriptgarden.info/). Se vuoi saltare direttamente alla sezione che contiene il post, quindi fare clic su [qui] (http://javascriptgarden.info/#function.arguments). –

+0

tnx, - sembra che implichino questo hack dà un po 'di velocità .. ma, davvero, solo ** non usarlo **. – c69

+2

@Aadit 'Function.call.apply' e' Funzione.apply' non può essere lo stesso qui perché il primo applica 'Function.call' mentre il secondo prova ad applicare il costruttore' Function'. Dettagli nella mia risposta, ma scommetto che se Ivo Wetzel fosse venuto a rispondere, sarebbe stato molto più eloquente e comprensibile. Questa è roba piuttosto profonda. Sono d'accordo che probabilmente non è qualcosa che dovresti usare a meno che tu non voglia che i colleghi spendano, oh non lo so, un 'ora e mezza a cercare di capirlo. :) –

risposta

13

No, Function.call.apply e Function.apply non sono le stesse in questo caso.

Diciamo che il chiamante originale invoca

Foo.method(t, x, y, z) 

Con chiamata e applicare insieme, come nel codice JavaScript Garden. Esegue

Function.call.apply(Foo.prototype.method, arguments); 

che è (vagamente, scrivendo arguments in matrice notazione):

Function.call.apply(Foo.prototype.method, [t, x, y, z]); 

che invoca Function.call con this==Foo.prototype.method:

Foo.prototype.method.call(t, x, y, z) 

che chiama Foo.prototype.method con this set di t e argomenti x, y e z. Dolce. Proprio come nei commenti. Abbiamo creato con successo un wrapper.

Supponiamo ora di aver detto solo Function.apply anziché Function.call.apply, che si sostiene sia semanticamente equivalente. Si dovrebbe

Function.apply(Foo.prototype.method, arguments); 

che è (vagamente)

Function.apply(Foo.prototype.method, [t, x, y, z]); 

che chiama la funzione Function (ugh!) Con this set per Foo.prototype.method e gli argomenti t, x, y, e z.

Non è affatto lo stesso.

+0

Ma qual è lo scopo di tale involucro? – c69

+3

Lo scopo è chiamare 'Foo.prototype.method' senza che sia associato a un'istanza di' Foo'. Invece si passa in _your proprio valore per essere usato come valore di 'this' all'interno di' Foo.prototype.method'. Perché dovresti farlo? Forse vuoi fare qualche programmazione funzionale e la funzione che vuoi mappare o ridurre o filtrare è un metodo vincolato. Se non lo vuoi legato ad un oggetto, chiami un "wrapper non associato". Questa è una terminologia strana, perché in definitiva leghi questo metodo al tuo oggetto (ma puoi ignorarlo ...) –

+0

Ok, da quello che ho capito le seguenti affermazioni sono equivalenti: Function.call.apply (Foo.prototype.method, argomenti); Foo.prototype.method.apply (argomenti [0], Array.prototype.slice.call (argomenti, 1)); Entrambi possono essere sostituiti per creare wrapper non associati. Tuttavia, il primo metodo è più breve, più veloce e più intuitivo. Eccezionale! –

4

Significa che è possibile utilizzare i metodi da un oggetto su un altro.

Un buon esempio è gli argomenti variabile tutte le funzioni hanno, è come una matrice, ma non una matrice in modo da poter chiamare i metodi di matrice su di esso così:

Array.prototype.join.call(arguments, ","); 
+1

Ma cosa fa il bit 'apply' nella domanda originale? –

+1

@ CameronSkinner: il metodo 'apply' di un oggetto funzione esegue quella funzione, trattando il primo argomento come' this' in quell'esecuzione e il secondo argomento come 'arguments'. 'fn.apply (a, [b, c])' è equivalente a 'fn.call (a, b, c)'. – eyelidlessness