Skip to content Skip to sidebar Skip to footer

Javascript __proto__ - Clarification?

I have this function : function Foo(){} According to this picture : >> Foo.prototype -> Foo {} So if I write : Foo.prototype.constructor Now - it reference

Solution 1:

Note: First off, __proto__ is non-standard, use Object.getPrototypeOf, though for shortness, and because I'm lazy, I did use prototype quite a few times in this answer

Well, you're thrown of by your initial assumption, if I'm reading you correctly:

Foo.prototype -> Foo{}

The prototype of Foo (which is a constructor) is, by definition an instance of Foo. But, because a constructor is a function, and a constructor returns an object of a particular instance, the prototype will be an augmented Object either way. I'm not a big fan of comparing prototypal ineritance to classical OOP, but think of it like this:

The Foo prototype is sort of a mutable class definition (you can add methods and properties as you go along), the constructor creates an object that augments this prototype, and adds another layer of properties/methods on an instance level. Hence Foo.prototype instanceof Foo is true. But, Foo being an object:

Object.getPrototypeOf(Foo.prototype) === Object.prototype

is true. Just as

Object.getPrototypeOf(Array.prototype) === Object.prototype.

Translate this to JS (prototype)-speak, and you get something like:

For each function object JS creates, this object is assigned a prototype property. The prototype property is an instance of Object, but it has 1 special property. If one attempts to access a property or method on an object, and JS cannot find this property defined at the instance level, JS will attempt to resolve the name on the prototype property:

instance.nonExistantProperty;
//js scans instance variable, doesn't find property:
instance.prototype.nonExistantProperty//js uses prototype, if not found:
instance.prototype.prototype.nonExistantProperty//all the way up to Object.prototype, which does not have a prototype, so here an exception is raised (TypeError is thrown)

Here's a short schematic representation of this lookup, which I copied from one of my older posts here, it might be worth a look, also check the linked answers at the bottom, they go into even more details on this matter

[      F.divide      ]<=========================================================\ \
F[divide] ===> JS checks instance forproperty divide                           | |
 /\ ||                                                                          | |
 || || --> property found @instance, return value-------------------------------| |
 || ||                                                                          | |
 || ===========> Function.prototype.divide could not be found, check prototype  | |
 ||      ||                                                                     | |
 ||      ||--> property found @Function.prototype, return-----------------------| |
 ||      ||                                                                     | |
 ||      ==========> Object.prototype.divide: not found check prototype?        | |
 ||          ||                                                                 | |
 ||          ||--> property found @Object.prototype, return---------------------|_|
 ||          ||                                                                 |=|
 ||          =======>prototype is null, return"undefined.divide"~~~~~~~~~~~~~~~|X|
 ||                                                                             \ /
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~< TypeError can't read property 'x' of undefined

That's basically it.

Now, perhaps you're also a tad thwarted as to why Foo.prototype.constructor references the Foo function. Again, this is quite easy, because each instance is expected to contain all information you might require to determine which type of object you're dealing with:

functionFoo{}
var inst = newFoo();
console.log(inst.constructor);//references the constructor function

Remember, all instances returned by Foo return an object, that references all of the prototype properties, and (optionally) some properties at instance level, too.

Why, then, would you even bother creating such instances? Again this is perfectly simple: changing an instance, does not change the prototype:

console.log(Foo.prototype.constructor === inst.constructor);//true
inst.constructor = function(){};//override constructor propertyconsole.log(Foo.prototype.constructor === inst.constructor);//false, prototype did not change

Post a Comment for "Javascript __proto__ - Clarification?"