|Written by Ian Elliot|
|Friday, 05 December 2014|
Page 1 of 3
There is a newer version of the draft of the book here.
The prototype object is a very strange idea and making sense of it depends on seeing the bigger picture. The prototype object is intimately tied up with the idea and use of a constructor to create objects.
The message is - don't make too much of the whole prototype idea.
The Prototype Delegation Principle
The actual prototype mechanism is very simple.
The question of how it gets set to reference another object is something that we will deal with later. For the moment what matters is that the [[prototype]] property is used to attempt to resolve any property references that the object does not support.
That is, if you try to use a property that hasn't been defined on an object then the system looks for it on the object that [[prototype]] references. That is the [[prototype]] references an object that will be used to delegate any properties or methods that the original object doesn't have.
This principle applies to all objects including any object referenced as a prototype. This means that if the prototype object doesn't have the property then its prototype object is searched and so on up the prototype chain.
The prototype chain ends when an object with a null [[prototype]] reference is encountered.
Many ways of creating an object set the [[prototype]] property to reference the object Object.prototype and this has its [[prototype]] property set to null so automatically ending the chain.
So what is the prototype chain for?
The simple answer is that it provides a default set of behaviors for an object. If you set object A's prototype to be object B then, without any extra work, A automatically seems to have all of the properties of B.
Clearly if the same prototype object is used for a lot of other objects then this default behavior is obtained without having to duplicate all of the code. That is, one reason for using prototypes is that it is more efficient.
Another reason is that if a set of objects all have a single prototype object then updating that object updates all of the objects that use it as a prototype.
Notice that this mechanism automatically shadows any prototype properties that the original object does implement. For example, if both A and B have property c then A.c accesses the property provided by A and B's property is shadowed or overridden by A's.
Properties that are directly provided by and object are known as its "own" properties. You can test to see if a property is directly provided using the hasOwnProperty function which is provided by the Object prototype. That is, any object that has Object in its prototype chain has access to a hasOwnProperty function - more of this later.
The idea of the prototype chain and the way it provides addtional properties for an object is fairly easy to understand. It is important that you keep this simplicity in sight while you get to grips with some of the messier details of how the prototype chain actually gets set up.
First two very simple and very basic settings of [[prototype]].
What this means is that all literal objects have the basic behaviour provided by Object.prototype.
Now we come to the new ES5 facility.
The new Object.create(obj) method can be ued to create a new object with obj as its prototype - that is with its [[prototype]] property referencing obj.
Consider, for example:
This first creates a literal object which is going to be used as a prototype for another object. Next Object.create is used to create a new empty object but with its [[prototype]] referencing myProto. Now when we try to use property a (or b or c) on the new object clearly it isn't found as an own property, but the search of the prototype chain leads directly to myProto and it does have property a which is used as if it was a property of myObject.
Notice that the prototype chain in this example is:
The literal object myProto has Object.prototype set as its prototype by default and Object.prototype has null as its prototype by default.
The only problem with Object.create is that it is not suported by older browsers. However it is very easy to create a polyfill based on the original method of setting a prototype object - see later for more details.
Now we have a way of setting an object's prototype object we can explore some of its implicatons.
Object Prototype Interactions
The prototype object, and more generally the prototype chain, brings behavior to an object without you having to reimplement it.
In the normal course of things a prototype object would be used more than once as a prototype. If it is only used once you might as well use the prototype as the main object as there is no advantage in delegating.
Now myObject1 and myObject2 have the same prototype object and hence the same values of a, b and c.
This raises the question of what happens if either of the objects tries to modify a property provided by the prototype?
The simple answer is that an object cannot modify a non-own property. For example, if you try:
you will discover that myObject1.a is 10 and myObject2.a is still 1. When you try to store a value in a property the prototype chain is mostly ignored and an own property is created. From this moment on the own property is used and the prototype object's property is overridden.
Note: There is a subtle twist to this in that if the prototype's property is set as read only then the assignment is disallowed and a prototype property is created.
The object may not be able to modify the prototype object but any modifications to the prototype are immediately communicated to the object using it.
results in both objects having a value of 10 for the a property - unless of course they have created an own property.
Using a prototype object to share data isn't often a good idea because as soon as the main object writes to a non-own property it is converted into an own property. This means you generally don't make any savings in storage when you supply data properties using a prototype.
|Last Updated ( Sunday, 10 May 2015 )|