2012-08-01 15 views
11

Sono un grande fan di ES2 Function.prototype.bind e argomenti currying (fondamentalmente creando argomenti predefiniti per le funzioni).Confusione su Function.prototype.bind()

Mi prendevo un po 'in giro, ma non riesco più a immaginare la mia vita. Questo è il mio parco giochi:

function hello(arg1, arg2) { 
    console.log('hello()'); 
    console.log('"this" is: ', this); 
    console.log('arguments: ', arguments); 
} 

var foo = Function.prototype.call.bind(hello,{what: 'dafuq'}, 2); 
foo(42); 

L'uscita registro per questo è la seguente:

hello() 
"this" is: Object{ what="dafuq" } 
arguments: [2,42] 

Ma io non capisco come mai l'oggetto {what: 'dafuq'} si fa strada come punto di riferimento per la this all'interno foo. Per quanto ho capito, stiamo creando una chiamata vincolata a Function.prototype.call. Consente di controllare la sinossi MDN per .bind() rapidamente:

fun.bind(thisArg[, arg1[, arg2[, ...]]]) 

così, thisArg per .call è la funzione hello, seguito dalla lista argomenti. Fondamentalmente quello che succede è questo

Function.prototype.call.call(hello, {what: 'dafuq'}, 2); 

... uuhhh ora il mio cervello fa male un po '. Penso di avere un'idea ora cosa succede, ma per favore qualcuno trovi belle parole solide per spiegarlo in dettaglio.

  • come {what: 'dafuq'} diventa il this reference

risposta

6

Ma io non capisco come mai l'oggetto {what: 'dafuq'} si fa strada come riferimento per il presente all'interno foo

È perché foo è in effetti il ​​metodo call con la funzione hello associata come contesto di chiamata e quell'oggetto associato come primo argomento. Il primo argomento di .callimposta il contesto di chiamata del relativo contesto di chiamata. Dal momento che lo hai legato, significa che l'oggetto è sempre il contesto di chiamata.


Mettiamola così ...

Hai tenuti contesto chiamando di .call-hello.

Questa è effettivamente la stessa facendo ...

hello.call(); 
// or... 
// Function.prototype.call.call(hello); 

hai anche legato il primo argomento di .call-{what: "dafuq"}, quindi questo è effettivamente la stessa facendo ...

hello.call({what: "dafuq"}); 
// or... 
// Function.prototype.call.call(hello, {what: "dafuq"}); 

E, infine, hai tenuti il ​​secondo argomento di .call-2, quindi questo è effettivamente la stessa facendo ...

hello.call({what: "dafuq"}, 2); 
// or... 
// Function.prototype.call.call(hello, {what: "dafuq"}, 2); 
+0

sì 'pippo' è il metodo di chiamata, ma non chiamiamo mai' foo.call (thisArg) 'giusto? lo chiamiamo direttamente con '()'. Non capisco: p – jAndy

+0

@jAndy: hai limitato il primo argomento di '.call' usando' .bind' al tuo oggetto. Quindi dal momento che questa "versione" di '.call' ha un primo argomento associato, lo userà sempre come contesto di chiamata. –

+0

la "versione" vincolata di '.call()' dovrebbe avere 'ciao' come thisArg, no? Dopodiché, eseguiamo quel '.call()' legato solo passando i parametri formali. Doh, beh potrebbe essere che sono bloccato mentalmente qui, ancora a pensarci. – jAndy

8

Non stai chiamando .bind(thisArg, args), ma
Function.prototype.bind.call(thisArgUsedByCall, thisArgUsedByBind, argument).

Un modo diverso di mostrare quello che succede:

// thisArgUsedByCall is a function 
Function.prototype.call(thisArgUsedByCall, ...) // does the same as: 
thisArgUsedByCall.bind(thisArgUsedByBind, argument); 
+0

ok, questo lo rende più ovvio. Buona risposta. – jAndy

2

La risposta breve è che legano consuma il primo argomento e lo usa come questo, ma poi la chiamata consuma il suo primo argomento (che era il secondo argomento di bind).

Bind funziona così:

fun.bind(thisArg, argArgs...)(x, y, ...) 

diventa

fun(argArgs..., x, y, ....) // this = thisArg 

Così

foo(42) 

è

Function.prototype.call.bind(hello, { what: 'dafuq' }, 2) (42) 

che diventa

Function.prototype.call({ what: 'dafuq' }, 2, 42) // this = hello 

chiamata funziona così:

fun.call(thisArg, argArgs) 

Diventa

fun(argArgs) // this = thisArg 

così

call({ what: 'dafuq' }, 2, 42) // this = hello 

diventa

hello(2, 42) // this = { what: 'dafuq' } 
+0

* "(Non so da dove viene quella 5)" * - Quali cinque? –

+0

Sembra risolto - è stato un errore di battitura nel post principale. Modificato la mia risposta in cambio. – royh