Why in JavaScript do both Object instanceof Function
and Function instanceof Object
return true
?
I tried it in Safari WebInspe
ALL objects have an internal property called [[Prototype]]. The value of this property is either null or an object and is used for implementing inheritance. If you try to look up a key on an object and it is not found, JavaScript will look for it in the prototype chain.
The Function constructor creates new Function objects (instances of Function constructor). The prototype property is specific to Function objects. The Function constructor is itself a Function object (instance of Function constructor).
When a Function object is used as a constructor, a new object will be created and the new object will have its [[Prototype]] initialized with the prototype property of the constructor.
function Dog () {}
var myCrazyDog = new Dog();
myCrazyDog.__proto__ === Dog.prototype // true
The language spec is that all objects are instances of Object constructor, and all functions are instances of Function constructor.
Object instanceof Function is true because Object is a function and thus is an instance of Function (Object is a Function object - an instance of the Function constructor). Object inherits from Function.prototype.
console.log(Object instanceof Function) // true
console.log(Object.__proto__ === Function.prototype) // true
Object instanceof Object is true because Object inherits from Function.prototype. Since Function.prototype is an object, it inherits from Object.prototype. Function instance of Object is true because Function inherits from Function.prototype. Since Function.prototype is an object, it inherits from Object.prototype. The prototype chain looks like this:
Object ---> Function.prototype ---> Object.prototype ---> null
Function ---> Function.prototype ---> Object.prototype ---> null
console.log(Object instanceof Object) // true
console.log(Object.__proto__ === Function.prototype) // true
console.log(Object.__proto__.__proto__ === Object.prototype) // true
console.log(Function instanceof Object) // true
console.log(Function.__proto__ === Function.prototype) // true
console.log(Function.__proto__.__proto__ === Object.prototype) // true
Function instanceof Function is true. Function is an instance of itself (naturally, since it’s a function, and thus an instance of Function). The prototype chain looks like this:
Function ---> Function.prototype ---> Object.prototype ---> null
console.log(Function instanceof Function) // true
console.log(Function.__proto__ === Function.prototype) // true
console.log(Function.__proto__.__proto__ === Object.prototype) // true
Thus keep in mind that the Function() and Object() constructors are functions. Since they are functions they are instances of the Function() constructor and inheriting from Function.prototype. Since Function.prototype is an object, Function.prototype is an instance of Object, thus inheriting from Object.prototype.
console.log(Object instance of Function) // true
console.log(Function instance of Function) // true
console.log(Function.prototype instanceof Object); // true
The source of the confusion in your question lies in the inherent dual nature of functions* in JavaScript (ECMAScript).
Functions in js are both regulars functions and objects at the same time. Think of them as algorithmic Dr. Jekyll and Mr. Hyde. They look like objects on the outside but inside they're just your good old js functions with all their quirks, or maybe it's the other way around!
JavaScript is really a tricky business :)
So back to your question, borrowing the syntax appearing on MDN:
object instanceof constructor
Applying it on the first statement in your code:
Object instanceof Function
Here you have Object
, a constructor function that's used as an object initializer but since functions lead a double life in js, it has object-specific props and methods attached to it rendering it effectively an object too.
So, the first condition in the statement has been met. We remain to investigate the other condition or operand.
Function
as you might have noticed is also function constructor but its other object side is of no interest to us now during the execution of this particular statement.
So, the syntactic conditions are both met namely "object" and "constructor". We can now then proceed to investigate their hereditary relation and if there's a connection between them.
Since Object
is a working function itself, it makes a lot of sense to assume that it has its internal prototype prop pointing to the Function.prototype
object reference since in js ALL functions inherit their props and methods through that same location Function.prototype
.
true
is definitely the ONLY expected outcome of this comparison performed by the instanceof
operator.
For the other case:
Function instanceof Object
Since we established already that functions in js have also an object side to them. It makes sense that they got their fancy object-specific toys from the Object.prototype
, and therefore they constitute instances of the Object constructor.
Hope I didn't add to the confusion with my explanation and allegories. :)
*: Not only functions that lead a double life in js. Almost all data types in js have an object dark side to them that facilitate completing operations and manipulations without any hassle.
Very Simple Explanation, Different from all answers
Both Object and Function are constructors(type of both with return "Function objects") and both are created from Function Constructor. The __proto__ property of both these point to 'Function.prototype' object.
QUICK EXPLANATION: __proto__ property of an object(say p1 which is Person type) points to the Constructor's protoype(say Person.prototype) Again the __proto__ in the prototype chain points to the object "Object.prototype".
BEFORE READING FURTHER PRINT DETAILS ON CHROME CONSOLE console.dir(Object), console.dir(Function)
KEEP IN MIND, function constructors and also objects so you will see both .prototype and __proto__ properties. In all the instance objects(say p1) you will only find the __proto__ property. The __proto__ is accessor for hidden property [[Prototye]] and best way to get is Object.getPrototypeOf(p1) as __proto__ is depricated.
(p1 instanceof Person) here operator checks if the Constructor Person's prototype is in the prototypal chain of the object p1. take a note that first value is instance object(p1) and second value is a constructor (Person).
Lets analyze => Function instanceof Object.
Function object's __proto__.__proto__ points to Object.prototype , So its true
Lets analyze => Object instanceof Function.
Object object's __proto__ points to Function.prototype, So its true
Hope this helps.
It took a while for me to figure out but its really worth the time spent. First, let us see how instanceof
works.
Quoting from MDN,
The
instanceof
operator tests whether an object has in its prototype chain theprototype
property of a constructor.
[instanceof]
Now, let us see how instanceof is defined by ECMA 5.1 Specification,
The production
RelationalExpression: RelationalExpression instanceof ShiftExpression
is evaluated as follows:
- Let
lref
be the result of evaluatingRelationalExpression
.- Let
lval
beGetValue(lref)
.- Let
rref
be the result of evaluatingShiftExpression
.- Let
rval
beGetValue(rref)
.- If
Type(rval)
is not Object, throw aTypeError
exception.- If
rval
does not have a[[HasInstance]]
internal method, throw aTypeError
exception.- Return the result of calling the
[[HasInstance]]
internal method ofrval
with argumentlval
.
First the left and right hand side expressions are evaluated (GetValue
) and then right hand side result should be an Object with [[HasInstance]]
internal method. Not all objects will have [[HasInstance]]
internal method, but functions. For example, the following will fail
console.log(Object instanceof {});
# TypeError: Expecting a function in instanceof check, but got #<Object>
[[HasInstance]]
Now, let us see how [[HasInstance]] has been defined in the ECMA 5.1 specification,
Assume
F
is a Function object.When the
[[HasInstance]]
internal method ofF
is called with valueV
, the following steps are taken:
- If
V
is not an object, returnfalse
.- Let
O
be the result of calling the[[Get]]
internal method ofF
with property name"prototype"
.- If
Type(O)
is not Object, throw aTypeError
exception.- Repeat
- Let
V
be the value of the[[Prototype]]
internal property ofV
.- If
V
isnull
, returnfalse
.- If
O
andV
refer to the same object, returntrue
.
It is so simple. Take the prototype
property of F
and compare it with the [[Prototype]]
internal property of O
until it becomes null
or prototype
of F
is the same as O
.
[[prototype]]
internal propertyFirst let us see what is the [[prototype]] internal property,
All objects have an internal property called
[[Prototype]]
. The value of this property is eithernull
or an object and is used for implementing inheritance. Whether or not a native object can have a host object as its[[Prototype]]
depends on the implementation. Every[[Prototype]]
chain must have finite length (that is, starting from any object, recursively accessing the[[Prototype]]
internal property must eventually lead to anull
value).
Note: We can get this internal property with the Object.getPrototypeOf function.
prototype
property[[HasInstance]]
also talks about another property called prototype, which is specific to the Function
objects.
The value of the
prototype
property is used to initialise the[[Prototype]]
internal property of a newly created object before the Function object is invoked as a constructor for that newly created object.
This means that, when a function object is used as a constructor, a new object will be created and the new object will have its internal [[Prototype]]
initialized with this prototype
property. For example,
function Test() {}
Test.prototype.print = console.log;
console.log(Object.getPrototypeOf(new Test()) === Test.prototype);
# true
Now let us get back to the actual question. Lets take the first case
console.log(Object instanceof Function);
# true
It will fetch Function.prototype
first and it will try and find if that object is in the prototype hierarchy of Object
. Let us see how that turns out
console.log(Function.prototype);
# [Function: Empty]
console.log(Object.getPrototypeOf(Object));
# [Function: Empty]
console.log(Object.getPrototypeOf(Object) === Function.prototype);
# true
Since the Function.prototype
matches the Object
's internal property [[Prototype]]
, it returns true
.
Now lets take the second case
console.log(Function instanceof Object);
# true
console.log(Object.prototype);
# {}
console.log(Object.getPrototypeOf(Function));
# [Function: Empty]
console.log(Object.getPrototypeOf(Function) === Object.prototype);
# false
console.log(Object.getPrototypeOf(Object.getPrototypeOf(Function)));
# {}
Object.getPrototypeOf(Object.getPrototypeOf(Function)) === Object.prototype
# true
Here, first we get the Object.prototype
, which is {}
. Now it is trying to find if the same object {}
is there in the Function
's prototype chain. Immediate parent of Function
is and Empty function.
console.log(Object.getPrototypeOf(Function));
# [Function: Empty]
It is not the same as Object.prototype
console.log(Object.getPrototypeOf(Function) === Object.prototype);
# false
But the [[HasInstance]]
algorithm doesn't stop there. It repeats and gets up one more level
console.log(Object.getPrototypeOf(Object.getPrototypeOf(Function)));
# {}
And this is the same as Object.prototype
. That is why this returns true
.
From MDN:
The instanceof operator tests whether an object has in its prototype chain the prototype property of a constructor.
Essentially, it is checking if Object
(not an instance of Object
, but the constructor itself) has as an instance of Function.constructor
somewhere up its prototype chain.
And, indeed:
> Function.__proto__.__proto__ === Object.prototype
true
> Object.__proto__ === Function.prototype
true
This explains why Object instanceof Function
as well as the reverse.
Object is a built-in constructor function for objects. It is therefore a function (an instance of Function). Functions are objects in JavaScript, it is therefore an object too (an instance of Object
).