I come across this code in jsGarden, and I cannot figure the meaning to chain call
and apply
together. Both will execute the function with a given context object, why it could be chained?
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);
};
It's making a call to
call
viaapply
; that is, it's usingcall
to call a function ("method"), and it's usingapply
to make the call because it's got the arguments in the form of an (almost) array.So to take it apart:
That's a reference to the
call()
function available on all Function instances, inherited from the Function prototype.That's a reference, via the reference to the
call
function, toapply
. Becauseapply
is referenced via thecall
object, when the call toapply
is made thethis
value will be a reference to thecall
function.So we're invoking the
call
function viaapply
, and passingFoo.prototype.method
to be thethis
value, and the arguments to "Foo.mmethod" as the arguments.I think it's basically the same effect as this:
but I'll have to try it to make sure. edit Yes that seems to be it. So I can summarize the point of that trick as being a way to invoke
apply()
when the desiredthis
value is the first element of the array holding the parameters. In other words, usually when you callapply()
you've got the desiredthis
object reference, and you've got the parameters (in an array). Here, however, since the idea is that you pass in the desiredthis
as a parameter, then it needs to be separated out in order for a call toapply
to be made. Personally I would do it as in my "translation" because it's a little less mind-bending (to me), but I suppose one could get used to it. Not a common situation, in my experience.The Code from Javascript Garden.
Notice that it state the
will become this:It means the apply() function will be excuated first, then the call() function will be execuated.
Pattern: The right most
call() / apply()
will get execuated firstapply()
will get executed firstapply()
becomes the caller of thecall()
function, so nowapply()
can only take one single array of parameters, soapply()
providesarguments
to thecall()
function, so nowExamples from @foxiris
1st One:
call()
will get execuated firstcall()
becomes the caller of theapply()
,so nowArray.apply()
call()
can accept multiple arugments, so it can providethis
and[1, 2]
toapply()
, so nowArray.apply(this, [1, 2]);
, which will output[1, 2]
2nd One:
apply()
will get execuated firstapply()
becomes the caller of thecall()
,so nowArray.call()
apply()
can only take one single array parameter, so it can only providethis
tocall()
, so nowArray.call(this);
, output is[]
.3rd One:
call()
will get execuated firstcall()
(right most one) becomes the caller ofcall()
(the second to the right), so nowArray.call()
call()
can take multiple parameters, so it can providethis
and[1, 2]
to anothercall()
, so nowArray.call(this, [1, 2]);
, output is[[1, 2]]
.I think the code should be like this:
then
Other examples:
apply
does take an array as the second argument,call
takes single parameters.So, the first
arguments
item will be thethis
value of themethod
, and the subsequent will fill the single parameters.The result is a static function
method
on theFoo
constructor, that takes aFoo
instance (or something similiar) as the first argument and applies the prototypemethod
on it. A possible usecase were to define aObject.hasOwnProperty
function, which is normally only available asObject.prototype.hasOwnProperty
.Ultimately, it makes the invocation of the
method
one "prototype" and one "call" shorter if you need to apply it on objects that a) don't inherit it or b) overwrite it.