Reputation: 2018
Lately I'm trying to get the technical aspects of the prototype chain. Now I have a few questions about object instantiation.
Consider the following code:
var Foo = function(s) {
this._bar = s;
};
var fooInst = new Foo('test');
Now when I examine the created object, then:
Foo.prototype === Function.prototype; // true
fooInst.prototype === ?
fooInst.prototype.prototype === Object.prototype; // true
I'm wondering, what fooInst.prototype
exactly is. In Chromes inspector it seems to be some kind of Foo
with an constructor
property. But all sources I read about prototypes state that fooInst.prototype === Foo.prototype
should be true.
So my question: how exactly does JS handle the prototype chain. What exactly happens when I call new Foo
.
Thanks in advance!
Edit
So I found, that (in Chrome) Object.getPrototypeOf(fooInst) === Foo.prototype;
is true
, but Object.getPrototypeOf(fooInst) === Object.getPrototypeOf(Foo)
is false
. Why that?
Upvotes: 3
Views: 554
Reputation: 322452
I'm wondering, what fooInst.prototype exactly is.
It is undefined
.
fooInst.prototype === undefined; // true
Only functions have an automatic .prototype
property. Objects do not.
If you create an object using a constructor, like:
var fooInst = new Foo('test');
...then fooInst
will have an internal reference to Foo.prototype
, but there's no standard property to get Foo.prototype
from fooInst
.
That said, there is a non-standard property that is supported in some JavaScript environments for referencing the prototype object.
fooInst.__proto__ === Foo.prototype; // true (if __proto__ supported)
Also, there is a method provided by ECMAScript 5 that can be used.
Object.getPrototypeOf( fooInst ) === Foo.prototype; // true
That internal reference from an object to its prototype object can be just the first in a chain of such references.
The prototype object likely has its own prototype object that is referenced. (In basic cases, this will be Object.prototype
, or with longer chains, Object.prototype
may be further down the chain.)
Object.prototype
itself references null
as its prototype. This ends the chain.
You should note that the internal reference from an object to its prototype object does not change if you change the .prototype
object of the constructor function. It is a reference that exists for the life of the object.
var Foo = function(s) {
this._bar = s;
};
var fooInst = new Foo('test');
Object.getPrototypeOf( fooInst ) === Foo.prototype; // true
// Change the prototype object of Foo
Foo.prototype = { some:'object' };
Object.getPrototypeOf( fooInst ) === Foo.prototype; // false
Upvotes: 6
Reputation: 827218
Your first assumption:
Foo.prototype === Function.prototype;
Is not right, I think you are mixing up the concept of the [[Prototype]]
internal property that all objects have, and makes the "link" of the prototype chain, and the prototype
property that function objects have.
The above comparison will produce false
because the value of the Foo.prototype
property is a new object, created at the time you created the Foo
function.
This object is initialized whenever you create a function object, it inherits from Object.prototype
and it has a property, named constructor
that points back to the function (Foo.prototype.constructor === Foo
), and it's used when you call your function as a constructor.
Now, if we talk about the [[Prototype]]
internal property, you are right, the [[Prototype]]
of your Foo
function is Function.prototype
in other words, Foo
inherits from Function.prototype
, e.g.:
Object.getPrototypeOf(Foo) === Function.prototype; // true
Foo instanceof Function; // true
Foo.__proto__ === Function.prototype; // true
About fooInst
this object was created in a new expression, when you used your Foo
function as a constructor, this new object is produced, and it inherits from Foo.prototype
, (its internal [[Prototype]]
property points to Foo.prototype
).
It doesn't have a prototype
property, since this property is only meaningful for function objects.
See also:
Upvotes: 2
Reputation: 62793
You might find the explanations and diagrams in JavaScript. The Core useful here.
All objects have a prototype chain. As such, fooInst
has a prototype chain, at the head of which is Foo.prototype
. When you called new Foo
, an Object was created, Foo.prototype
was set as its prototype chain and the constructor function was called in the context of the new Object.
Some browsers expose this as a non-standard __proto__
property, such that:
fooInst.__proto__ === Foo.prototype
Upvotes: 1