Let's try to break this down into more manageable pieces.
String
is a constructor (or a static function / constructor hybrid, whatever you want to call it), and as such, it inherits from Function.prototype
, because it is a function.
call
is a function that executes its context (the this
) with the context given to it in the first parameter:
console.log(String.call(true));
console.log(Array.call(null));
console.log(Function.call('so?'));
console.log(Object.call(/notice me/));
Let's look at a more official definition for Function.call()
:
The call()
method calls a function
with a given this
value and arguments
provided individually.
function.call(thisArg, arg1, arg2, ...)
Now, the interesting part here is noting that these three are identical:
'use strict';
var callRef = String.call; // Function.call, Array.call, Boolean.call, all of them are ===
console.log(String(/make me into a string/));
console.log(String.call(undefined, /make me into a string/));
console.log(callRef.call(String, undefined, /make me into a string/));
The callRef.call(String)
means, call callRef()
with the context of String
, which is to say, execute String()
with the context and parameters provided in the following arguments.
As we recall, the context doesn't really matter, but now we know that the first parameter of callRef.call()
does matter, because it determines what function to execute, because it's telling callRef()
what its context is, which gets executed as a function with the context provided in the next parameter.
Now reflecting on the initial question, what happens when we attempt to execute String.call.call()
? Well, if a parameter is not specified, it is undefined
, and we know that typeof undefined !== 'function'
.
So here's my final answer:
String.call.call()
is indeed a function... but all it's doing is attempting to execute undefined
as a function, which obviously isn't.
I hope this has been an interesting and informative explanation.