bufferoverflow76 bufferoverflow76 - 1 year ago 212
Javascript Question

Javascript Function.prototype.call()

I read some article and it said the following 2 line are doing the same thing.

fn.call(thisValue);
Function.prototype.call.call(fn, thisValue);


For line 1, my understanding is that every function object in Javascript do have a the method
call
inherited from the
Function.prototype
and what
call
method does is to have the
this
keyword inside the function definition of
fn
to be
thisValue
(the first parameter I passed in the call method.
fn
is a function so what I am doing in
fn.call(thisValue)
is just invoking
fn
and set the
this
keyword inside the function to be
thisValue
.



But For line 2, I don't get it. Can someone help to explain it what the hack the line 2 is doing.

Answer Source

Let's start with this setup:

function fn() { console.log(this); }
var thisvalue = {fn: fn};

Now you surely understand that thisvalue.fn() is a method call, and sets the logged this value to the thisvalue object.

Next, you seem to know that fn.call(thisvalue) does exactly the same call. Alternatively, we could write (thisvalue.fn).call(thisvalue) (parentheses just for structure, could be omitted) as thisvalue.fn === fn:

thisvalue.fn(…); // is equivalent to
(thisvalue.fn).call(thisvalue, …); // or:
(fn).call(thisvalue, …);

OK, but fn.call(…) is just a method call as well - the call method of functions is called on the fn function.
It can be accessed as such because all function objects inherit this .call property from Function.prototype - it's not an own property like .fn on the thisvalue object. However, fn.call === Function.prototype.call is the same as thisvalue.fn === fn.

Now, we can rewrite that method call of .call as an explicit invocation with .call():

fn.call(thisvalue); // is equivalent to
(fn.call).call(fn, thisvalue); // or:
(Function.protoype.call).call(fn, thisvalue);

I hope you spot the pattern and can now explain why the following work as well:

Function.prototype.call.call.call(Function.prototype.call, fn, thisvalue);
var call = Function.prototype.call; call.call(call, fn, thisvalue);

Breaking this down is left as an exercise to the reader :-)

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download