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?
Let me show you an example.
function a() { console.log(1) }
function b() { console.log(2) }
a.call(b) // 1
a.call.call(b) // 2
a.call.call.call(b) // 2
Why?
We know a.call(b)
means invoke a()
with this value b
.
So that a.call.call(b)
means invoke Function.prototype.call()
with this value b, same as Function.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.
Function.prototype.call.call(a) // 1
Function.prototype.call.call(b) // 2
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 means a()
.
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()
means a.call.call(undefined)
means a.call.call(window)
means invoke window
.
Try to invoke window
you'll get Uncaught TypeError: window is not a function
, so try to invoke a.call.call()
you'll get Uncaught TypeError: a.call.call is not a function
.
Hope it helps.
Starting from the basic stuff,
What is .call
? its a function available inside Function.prototype
.
So that it can be called on any function, thats exactly why you are able to call a.call
.
Now, What does a .call
do ? it sets this
context on the function you called .call
on. so in your case, when you call a.call
it can set a this
context on function a
(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 case a
),
so for simplicity you assume, inside the .call
it might be calling the function like this()
(and that is nothing but calling a()
) - so far so good
to your question
a.call.call
what is happening here ? the second .call
(i am counting left to right) is calling first .call
and setting this
for the first .call
, which is nothing but the first parameter, which is a function.
now first .call
will call this()
(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 function a
gone in all this confusion ?
which is actually not involved as soon as yo call second .call
(here this
to first .call
is coming from second .call
which makes your function a
obsolete in this case )
in you case .call.call
should have been called on Function.prototype
or Object
or any other function (remember .call
is part of Function.prototype
and can be called on any function)
so you should have done
Function.prototype.call.call(...)
or even
Object.call.call(...)
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 HERE
i 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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With