prototype vs __proto__
Javascript is prototyping language right. Which is "more powerful" than object oriented programming.. since you could "easily" emulate object inheritance with prototypes, but it is hard to emulate prototyping features with classes and objects. Or at least that is the theory.
But wrapping your head around prototypes is not as easy as advertised. I had to scratch my head on multiple occasions with "wtf how this works exactly". The prototype chain can be influenced through Object.create(__proto__, properties). Where the __proto__ parameter is the object from which you want to have as immediate parent in the prototype chain.
the layout of the objects is as follows:
true:
Now, lets consider examples with constructor functions where the prototype property becomes very important.
Since all functions could act as constructors to create new objects - they all have default empty prototype object. The object diagram in this case is (yeah.. a lot of objects, for a single function, i.e. for a single constructor)
This are all valid walk throughs the various prototype chains:
Now looking at the maze of prototype and __proto__ links, which of this are true:
And finally the complete picture when we add some methods to the prototype and the instance:
The object diagram in this case will look like:
Thus if you have read carefully through the confusing labyrinth of links between objects, the following are the conclusions:
Class-based object-oriented languages, such as Java and C++, are founded on the concept of two distinct entities: classes and instances.
...
A prototype-based language, such as JavaScript, does not make this distinction: it simply has objects. A prototype-based language has the notion of a prototypical object, an object used as a template from which to get the initial properties for a new object. Any object can specify its own properties, either when you create it or at run time. In addition, any object can be associated as the prototype for another object, allowing the second object to share the first object's properties.
But wrapping your head around prototypes is not as easy as advertised. I had to scratch my head on multiple occasions with "wtf how this works exactly". The prototype chain can be influenced through Object.create(__proto__, properties). Where the __proto__ parameter is the object from which you want to have as immediate parent in the prototype chain.
prototype vs __proto__
The __proto__ property is not standard until ECMAScript 5, and is not supported in some older browsers. But still it is massively supported by most modern browsers to the extend that it will be included in ECMAScript 6. The prototype chain is implemented in Javascript by going through the __proto__ properties until null is reached.
The prototype property is supported on all objects that are functions (i.e. their __proto__ === Function.prototype), i.e. they could act as constructors. When instance of a constructor is created with new, then the __proto__ of the newly created instances is pointed to the object pointed by prototype.
Lets consider this simple example:
var parent = { a : 1 }; // parent inherits from Object.prototype as all objects do. // Inheritance is implemented only via the __proto_. This means // that: parent.__proto__ === Object.prototype // The prototype property is defined only for Function objects, // i.e. parent.prototype === undefined var child = Object.create(parent); // Object.create creates a new object and sets its __proto__ // to the "parent" parameter (the easiest way to prototype), i.e.: // child.__proto__ == parent // Since child is normal object, and not Function object, the // child.prototype === undefined child.b = 2;
the layout of the objects is as follows:
child.__proto__ === parent parent.__proto__ === Object.prototype.__proto__ Object.prototype.__proto__ === null
Now, lets consider examples with constructor functions where the prototype property becomes very important.
function Shape() { this.instance_id = "Shape_" + Shape.prototype.getNextId(); }
Since all functions could act as constructors to create new objects - they all have default empty prototype object. The object diagram in this case is (yeah.. a lot of objects, for a single function, i.e. for a single constructor)
This are all valid walk throughs the various prototype chains:
Shape.prototype.__proto__ === Object.prototype Object.prototype.__proto__ === null Shape.prototype.__proto__.__proto__ === null Shape.__proto__ === Function.prototype Shape.__proto__.__proto__ === Object.prototype
Now looking at the maze of prototype and __proto__ links, which of this are true:
Shape.__proto__ === Function.prototype Shape.prototype === Function.prototype Shape.prototype.__proto__ === Function.prototype.__proto__
And finally the complete picture when we add some methods to the prototype and the instance:
function Shape() { this.instance_id = "Shape_" + Shape.prototype.getNextId(); } Shape.prototype.id = 0; Shape.prototype.getNextId = function() { return this.id++; } Shape.prototype.toString = function() { console.log("This is: "+this.instance_id ); } // Crate new objects of type Shape var sh1 = new Shape(); var sh1 = new Shape();
The object diagram in this case will look like:
The sh1 and sh2 objects gets its __proto__ set to the Shape.prototype!
Thus they get access to the id, getNextId() and toString().
|
- Method and properties are inherited only through the __proto__ chain !
- Only the functions have prototype object
- When creating new object, i.e.: var
= new then.__proto__ is set to.prototype . (where - Setting methods and properties to
.prototype will be accessible invia the __proto__ links
Comments
Post a Comment