Function is an Object?
If you regularly read articles about Javascript, you will probably see people often say: "Oh function is actually an object". But wait, If it is like that then:
- Why
typeofoffunctionis return "function" instead of "object"? - How we can make a function call on an object?
In this article, we're going to "investigate" whether that's the case and clear up misunderstandings about functions.
1. Does typeof return the data type?
Firstly, we need to know about list of data type in Javascript:
- undefined
- null
- boolean
- string
- symbol
- number
- bigint
- Object
Learn more at: ECMAScript Specification
As you see, there is no one called 'function'. But let's run this code below:
function foo() {}
console.log( typeof foo); // -> 'function' - WHAT?
So are we wrong or does typeof really have a "problem" 🤔?
The typeof Operator
To understand how this function works, we need to search the ECMAScript specification document at Section 13.5.3. There are the steps of typeof function but just focus on step 5th:
5. Return a String according to Table 41.
Looking at the last row, if an Object already has a Call method implemented then return "function". Instead of returning the left column (Type of val), typeof returns a string value in the right column. So we can say, typeof does not implicitly return the type.
At this point, we have a clue that the function is actually an object. But this Object is so strange 😬
2. Function object
Then what is Call method?. According ECMAScript specification, function object contains two internal methods: Call and Construct. The Call method must be implemented. Note that internal methods are only called in the Javascript engine, they are not a method of an object. In particular we cannot view them via ".", for example foo.construct.
- Call: Executes code associated with this object. Invoked via a function call expression.
- Construct: Creates an object. Invoked via the new operator or a super call.
So to summarize, we can say: an object is considered a function object only if it implements the Call method. Every object that supports Construct must support Call.
3. Function Definitions
So how does Javascript create a function object when we declare it?
Function Declaration
function foo() {
return 0;
}
The above is a common way of declaring a function. Now let's see how the Javascript engine works.
Firstly, we divide the above statement into small parts according to the following pattern:
function Name ( Parameters ) { FunctionBody }
There are steps that Javascript Engine process:
(I have omitted the steps that are not in the scope of the article)
- Let
namebe string value of Name. - Let
FbeOrdinaryFunctionCreate(Function.prototype, Parameters, FunctionBody). - Perform
SetFunctionName(F, name). - Perform
MakeConstructor(F). - Return
F.
It has three functions we need to consider OrdinaryFunctionCreate,SetFunctionName,MakeConstructor and at the end it returns an function object F.
Note: Those functions are internal abstract function, Javascript need to implement them in its engine. We can't call them in our code as well.
OrdinaryFunctionCreate Function
It is used to specify the runtime creation of a new function with a default Call internal method and no Construct internal method. It returns a function object.
There are steps:
(I have omitted the steps that are not in the scope of the article)
- Let
FbeOrdinaryObjectCreate(Function.prototype) - Set
F.[[Call]]implement. - Return
F
We found a new function OrdinaryObjectCreate, It is used to specify the runtime creation of new ordinary objects, it also set Function.prototype into F. And you see, in step 2, Javascript Engine already implement the Call method.
At this point, we know how Javascript assigns the Call method.
SetFunctionName Function
It adds a "name" property to F.
function foo() {}
console.log( foo.name ); // -> "foo"
MakeConstructor Function
It creates a constructor. Invoked via the new operator or a super call. But a function object is not necessarily a constructor and such non-constructor function objects do not have a Construct internal method.
4. Function Call
Function call is one of Left-Hand-Side Expressions. Javascript engine will invoke EvaluateCall function (It is internal function) with the foo function as a parameter func. EvaluateCall run following this steps:
- If
Type(func)is not Object, throw a TypeError exception. - If
IsCallable(func)is false, throw a TypeError exception. - Return ?
Call(func).
At step 1, if statement will check type of func is object or not.
"hello"()
//-> Uncaught TypeError: "hello" is not a function
At step 2, IsCallable (internal function) will check Call already implemented or not.
let obj = {};
obj()
//-> Uncaught TypeError: obj is not a function
Finally, the Call() function will be called, which will call the Call method inside the function as we mentioned in OrdinaryFunctionCreate Function.
At this point, we can understand that even though a function is an object, but an object cannot be called as a function.

Top comments (2)
If you don't know, the main reason to have functions be objects is to support this business:
Once you support lexical closure—allowing inner functions to capture variables from an outer scope—functions have to be objects, because the captured variables have to be stored somewhere.
Wow great, I don't know this one. Thanks for your sharing