2012-08-01 12 views
11

Ich bin ein großer Fan von ES5 Function.prototype.bind und currying Argumente (im Grunde erstellen Standardargumente für Funktionen).Confusion über Function.prototype.bind()

Ich habe ein bisschen herumalbern, aber ich kann nicht für das Leben von mir herausfinden, mein eigenes Konstrukt mehr. Das ist mein Spielplatz:

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); 

Die Protokollausgabe hierfür ist wie folgt:

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

Aber ich verstehe nicht, wie auf der Erde die {what: 'dafuq'} Objekt seinen Weg als Referenz macht sich für die this innerhalb foo. Soweit ich es verstehe, erstellen wir einen gebundenen Anruf zu Function.prototype.call. Lets überprüfen Sie die MDN Synopsis für .bind() schnell:

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

so, thisArg für .call ist die hello Funktion, durch die Argumente Liste gefolgt. Grundsätzlich was passiert, ist dies

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

... uhhhh jetzt schmerzt mein Gehirn ein wenig. Ich denke, ich habe jetzt eine Idee, was passiert, aber bitte findet jemand schöne Worte, um es im Detail zu erklären.

  • wie {what: 'dafuq'} die this reference

Antwort

6

Aber ich verstehe nicht, wie auf der Erde das {what: 'dafuq'} Objekt seinen Weg als Referenz für die dies macht in foo

Das liegt daran, dass foo effektiv die call-Methode mit der hello-Funktion ist, die als aufrufender Kontext gebunden ist, und dieses Objekt als erstes Argument gebunden ist. Das erste Argument von .calllegt den aufrufenden Kontext seines Aufrufkontexts fest. Da Sie es gebunden haben, bedeutet dies, dass das Objekt immer der aufrufende Kontext ist.


es so sagen ...

Sie haben den Aufruf Kontext von .call-hello gebunden.

Dies ist das Gleiche wie zu tun ...

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

Sie haben gebunden auch das erste Argument von .call-{what: "dafuq"}, so ist dies das Gleiche wie zu tun ...

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

Und schließlich haben Sie das zweite Argument von .call-2 gebunden, so ist dies das Gleiche wie zu tun ...

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

ja 'foo' ist die Call-Methode, aber wir nennen nie' foo.call (thisArg) 'richtig? wir nennen es einfach direkt mit '()'. Ich verstehe es nicht: p – jAndy

+0

@jAndy: Sie haben das erste Argument von '.call' mit' .bind' an Ihr Objekt gebunden. Da diese "Version" von ".call" ein gebundenes erstes Argument hat, wird es immer als aufrufender Kontext verwendet. –

+0

die gebundene "Version" von '.call()' sollte 'hallo' als thisArg, nein haben? Danach führen wir diese gebundene '.call()' nur übergeben formale Parameter. Doh, na ja, ich bin hier nur mental blockiert, ich denke immer noch daran. – jAndy

8

wird Sie sind nicht .bind(thisArg, args) nennen, aber
Function.prototype.bind.call(thisArgUsedByCall, thisArgUsedByBind, argument).

Eine andere Art und Weise zu zeigen, was passiert:

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

ok, das macht es offensichtlicher. Gute Antwort. – jAndy

2

Die kurze Antwort ist, dass bindet das erste Argument verbraucht und verwendet es als dieses, aber dann verbraucht sein erstes Argument (das Bind's zweites Argument war).

Bind funktioniert wie folgt:

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

wird

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

So

foo(42) 

ist

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

die

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

Anruf wird funktioniert wie folgt:

fun.call(thisArg, argArgs) 

Wird

fun(argArgs) // this = thisArg 

so

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

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

* "(Ich weiß nicht, woher diese 5 kommt)" * - Welche fünf? –

+0

Sieht aus, als ob es repariert wurde - es war ein Tippfehler in der Hauptpost. Bearbeitete meine Antwort im Gegenzug. – royh