These codes are run on chrome devtool.
It seems like b.call
(same as a.call.call
) is calling the first argument, which is a function, then pass the second argument as this
.
If the first argument is not a function, then throw not a function
error.
Can someone explain how <Function>.call.call
work?
Starting from the basic stuff,
What is
.call
? its a function available insideFunction.prototype
. So that it can be called on any function, thats exactly why you are able to calla.call
.Now, What does a
.call
do ? it setsthis
context on the function you called.call
on. so in your case, when you calla.call
it can set athis
context on functiona
(through the first parameter you pass to the.call
function).what is
this
inside the.call
function ? it is nothing but the function you called.call
on(in your casea
),so for simplicity you assume, inside the
.call
it might be calling the function likethis()
(and that is nothing but callinga()
) - so far so goodto your question
what is happening here ? the second
.call
(i am counting left to right) is calling first.call
and settingthis
for the first.call
, which is nothing but the first parameter, which is a function.now first
.call
will callthis()
(remember this is set by the second.call
and it is the first param you passed and this is a function).i hope, i could explain what i intended to explain.
let me tell why you got confused with
a.call.call
. it is because you are thinking where did my functiona
gone in all this confusion ? which is actually not involved as soon as yo call second.call
(herethis
to first.call
is coming from second.call
which makes your functiona
obsolete in this case )in you case
.call.call
should have been called onFunction.prototype
orObject
or any other function (remember.call
is part ofFunction.prototype
and can be called on any function)so you should have done
or even
Now i was confused about these thing last week(not
.call.call
but.call.bind
), i asked a question here, and somebody explained it to me in very detailed, you can find it HEREi tried to answer from my understanding from the question i asked.
after all this is what SO is for
UPDATE:
you question "It seems like b.call(same as a.call.call) is calling the first argument, which is a function, then pass the second argument as this. If the first argument is not a function, then throw not a function error."
your assumption is correct here
Let me show you an example.
Why?
We know
a.call(b)
means invokea()
with this valueb
.So that
a.call.call(b)
means invokeFunction.prototype.call()
with this value b, same asFunction.prototype.call.call(b)
.But
Function.prototype.call.call()
is not an ordinary function Object. It can be invoked but it has no property. There's some unique rules to invoke it.In fact,
Function.prototype.call.call(b)
is an Exotic Object, furthermore, a Bound Function Exotic Object.[Specification] A bound function is an exotic object that wraps another function object.
[Specification] Calling a bound function generally results in a call of its wrapped function.
So that
Function.prototype.call.call(a)
simply meansa()
.a.call.call(x)
means invoke x, that is,x()
.Function.prototype.call(thisArg)
, if thisArg is undefined or null, it will be replaced by global object.a.call.call()
meansa.call.call(undefined)
meansa.call.call(window)
means invokewindow
.Try to invoke
window
you'll getUncaught TypeError: window is not a function
, so try to invokea.call.call()
you'll getUncaught TypeError: a.call.call is not a function
.Hope it helps.