I'm a huge fan of ES5's Function.prototype.bind
and currying arguments (basically creating default arguments for functions).
I was fooling around with that a bit, but I can't for the life of me figure out my own construct anymore. This is my playground:
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 );
The log output for this is as follows:
hello()
"this" is: Object{ what="dafuq" }
arguments: [2,42]
But I don't understand how on earth the {what: 'dafuq'}
object makes its way as a reference for the this
within foo
. As far as I understand it, we are creating a bound call to Function.prototype.call
. Lets check the MDN synopsis for .bind()
quickly:
fun.bind(thisArg[, arg1[, arg2[, ...]]])
so, thisArg
for .call
is the hello
function, followed by the arguments list. Basically what happens is this
Function.prototype.call.call( hello, {what: 'dafuq'}, 2);
...uuhhh now my brain hurts a little. I think I have an idea now what happens, but please someone find nice solid words to explain it in detail.
- how
{what: 'dafuq'}
bees thethis reference
I'm a huge fan of ES5's Function.prototype.bind
and currying arguments (basically creating default arguments for functions).
I was fooling around with that a bit, but I can't for the life of me figure out my own construct anymore. This is my playground:
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 );
The log output for this is as follows:
hello()
"this" is: Object{ what="dafuq" }
arguments: [2,42]
But I don't understand how on earth the {what: 'dafuq'}
object makes its way as a reference for the this
within foo
. As far as I understand it, we are creating a bound call to Function.prototype.call
. Lets check the MDN synopsis for .bind()
quickly:
fun.bind(thisArg[, arg1[, arg2[, ...]]])
so, thisArg
for .call
is the hello
function, followed by the arguments list. Basically what happens is this
Function.prototype.call.call( hello, {what: 'dafuq'}, 2);
...uuhhh now my brain hurts a little. I think I have an idea now what happens, but please someone find nice solid words to explain it in detail.
- how
{what: 'dafuq'}
bees thethis reference
3 Answers
Reset to default 8You're not calling .bind(thisArg, args)
, but
Function.prototype.bind.call(thisArgUsedByCall, thisArgUsedByBind, argument)
.
A different way to show what happens:
// thisArgUsedByCall is a function
Function.prototype.call(thisArgUsedByCall, ...) // does the same as:
thisArgUsedByCall.bind(thisArgUsedByBind, argument);
But I don't understand how on earth the
{what: 'dafuq'}
object makes its way as a reference for the this within foo
It's because foo
is effectively the call
method with the hello
function bound as the calling context, and that object bound as the first argument. The first argument of .call
sets the calling context of its calling context. Since you've bound it, it means that object always be the calling context.
Put it this way...
You've bound the calling context of .call
to hello
.
This is effectively the same as doing...
hello.call();
// or...
// Function.prototype.call.call(hello);
You've also bound the first argument of .call
to {what: "dafuq"}
, so this is effectively the same as doing...
hello.call({what: "dafuq"});
// or...
// Function.prototype.call.call(hello, {what: "dafuq"});
And finally, you've bound the second argument of .call
to 2
, so this is effectively the same as doing...
hello.call({what: "dafuq"}, 2);
// or...
// Function.prototype.call.call(hello, {what: "dafuq"}, 2);
The short answer is that bind consumes the first argument and uses it as this, but then call consumes its first argument (which was bind's second argument).
Bind works like this:
fun.bind(thisArg, argArgs...)(x, y, ...)
bees
fun(argArgs..., x, y, ....) // this = thisArg
So
foo( 42 )
is
Function.prototype.call.bind( hello, { what: 'dafuq' }, 2 ) ( 42 )
which bees
Function.prototype.call({ what: 'dafuq' }, 2, 42) // this = hello
Call works like this:
fun.call(thisArg, argArgs)
Bees
fun(argArgs) // this = thisArg
so
call({ what: 'dafuq' }, 2, 42) // this = hello
bees
hello(2, 42) // this = { what: 'dafuq' }