Javascript __proto__ - Clarification?
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?"