How does __proto__ differ from constructor.prototype?
I've been trying to wrap my head around this recently and finally came up with this "map" that I think sheds full light over the matter
http://i.stack.imgur.com/KFzI3.png
I know I'm not the first one making this up but it was more interesting figuring it out that finding it :-). Anyway, after that I found e.g. this another diagram that I think says basicly the same:
Javascript object layout
The most surprising thing for me was discovering that Object.__proto__
points to Function.prototype
, instead of Object.prototype
, but I'm sure there's a good reason for that :-)
I paste the code mentioned in the image here as well for if anyone wants to test it. Note that some properties are added to the objects for making easy to know where we are after some jumps:
Object.O1='';
Object.prototype.Op1='';
Function.F1 = '';
Function.prototype.Fp1 = '';
Cat = function(){};
Cat.C1 = '';
Cat.prototype.Cp1 = '';
mycat = new Cat();
o = {};
// EDITED: using console.dir now instead of console.log
console.dir(mycat);
console.dir(o);
constructor
is a pre-defined [[DontEnum]] property of the object pointed to by the prototype
property of a function object and will initially point to the function object itself.
__proto__
is equivalent to the internal [[Prototype]] property of an object, ie its actual prototype.
When you create an object with the new
operator, its internal [[Prototype]] property will be set to the object pointed to by the constructor function's prototype
property.
This means that .constructor
will evaluate to .__proto__.constructor
, ie the constructor function used to create the object, and as we have learned, the protoype
property of this function was used to set the object's [[Prototype]].
It follows that .constructor.prototype.constructor
is identical to .constructor
(as long as these properties haven't been overwritten); see here for a more detailed explanation.
If __proto__
is available, you can walk the actual prototype chain of the object. There's no way to do this in plain ECMAScript3 because JavaScript wasn't designed for deep inheritance hierarchies.