Just JavaScript - The Prototype Mechanism
Written by Ian Elliot   
Friday, 05 December 2014
Article Index
Just JavaScript - The Prototype Mechanism
Extended role of the constructor
Object factories and prototype

Object Factories and Prototype

If you want to use an object factory rather than a constructor you can still arrange it to set the object's prototype without requiring the explicit use of new. 

All you have to do is make use of the new operator to create a dummy function , set its prototype property and then use it to create an empty object with its prototype chain set.

For example, a factory method for the point object is:

function Point(){
 var F=function(){};
 F.prototype=pointMethods;
 obj=new F();
 obj.x=0;
 obj.y=0;
 return obj;
}

This may look a little strange but it is perfectly good. F is a function object that does nothing. Its prototype property is set to pointMethods and then the new operator is used to call it as a constructor. It constructs an empty object i.e. {} but with its [[prototype]] set to pointMethods. After this the factory method builds the object in the usual way and can be called without needing a new:

var point1 = Point();
var point2 = Point();
point1.setxy(10,200);
console.log(point1.x,point1.y);

You should be able to see that this also provide a polyfill for the Object.create method:

function ObjectCreate(proto){
 var F=function(){};
 F.prototype=proto;
 return new F();
}

This simply returns an empty object with its prototype set to proto, just like the Object.create(proto) method. 

Prototypes of built-in objects

One of the confusing things for a beginner is that functions aren't the only built-in objects that have a prototype property. Again it is important to remember that it is the internal [[prototype]] property that determines an object's prototype chain. If an object also has a prototype property then it is serving an additional purpose - usually to let you access the prototype directly. 

Each of the built-in objects has a unique standard prototype chain for its instances. 

Simple object instances have a single object prototype chain

object  -> object prototype -> null

All of the other special object instances - boolean, number, string, array, date and so on have an additional prototype object before object prototype. For example

string->string prototype->object prototype ->null

Some of the prototypes earlier in the chain over ride methods provided by the object prototype. For example, the object prototype provides both toString and toValue and these are both overriden by the string prototype. 

Of course these prototypes are referenced by the internal [[prototype]] property and this means you cannot get at them via the instances. To allow you to access and modify the prototype object of each of the built-in types the constructors for each of the objects has a prototype property just like a function constructor. 

For example, 

Object.prototype 

is a reference to the object prototype object. So if you want to add a property to the prototype object used by every object in JavaScript you would write:

Object.prototype.myprop=function(){
            console.log("Object Proto");};

Following this you can write 

var obj={};
obj.myprop;

and the prototype chain will provide the function.

As the object prototype is the final object in all of the prototype chains you can also write:

var fun=function(){};
fun.myprop;

or

var array=[1,2,3];
array.myprop;

If you only want to add or modify a property of a specific object type then you can change just its specific prototype. For example to change the function prototype you would use:

Function.prototype.myprop=function(){console.log("Function Proto");}

Now when you try:

var fun=function(){};
fun.myprop;

you will see Function Proto but when you try 

var obj={};
obj.myprop;

you will still see Object Proto. 

Modifying and adding to the built-in objects instance prototypes is a way of modifying and extending the behavior of every instance of the type. 

This is generally considered to be a bad idea and you are warned not to do it by everyone. Part of the reason is that a well-known library called Prototype got into all sorts of trouble by adding features to the built-in object, but this was mainly because it caused interoperability problems with other libraries. There is nothing intrinsically wrong with adding functionality to the built-in instance object prototypes as long as you can ensure there will be no clashes and it is made clear what is happening. 

Using Prototypes

You can think of the prototype mechanisms as providing some sort of inheritance - but it certainly doesn't bring with it any of the other pillars of OOP, encapsulation and polymorphism say. It is a much simpler and much more direct mechanism to make code sharing possible. 

If you have a single object then there isn't much practical advantage in designing a prototype object for it. On the other hand having a prototype object with all of the methods that the object is using does provide an organization. The object then has just the instance variables and the methods are all provided by the prototype. If things change and you need a second object, or more objects, then the prototype provides an easy solution. 

You can go a step further and construct a chain of prototype objects, each one adding more specialized functionality. This is the JavaScript equivalent of an inheritance hiearchy, but notice it has none of the implications of a type hierarchy. In JavaScript an object is basically a bag of properties and as such it can have new ones added and existing ones removed.

As there is no class based type in JavaScript you can't make use of polymorphism either. A variable references an object and the variable's type doesn't come into the matter of which method is called - this is determined by the object the variable references. 

The bottom line is that there may be situations in which a prototype hierarchy makes sense, but it isn't the default architecture as it is in a class-based language.

There is an argument for regarding prototype objects as method libraries for other objects. 

Summary

  • All objects have an internal [[prototype]] property that references a prototype object. 
  • The prototype object also has a [[prototype]] property that references a prototype object and so on forming a prototype chain. The chain ends with a null object.
  • When a property cannot be found on an object the system searches the prototype chain to find it. The first prototype object to support the property is used. 
  • A property provided directly by the object is called an own property. 
  • You can set the prototype of an object using Object.create(prototype) which returns an empty object with [[prototype]] referencing the given prototype object. 
  • The prototype chain is live in the sense you can update it at any time.
  • If an object tries to assign to a property provided by the prototype chain then it immediately creates an own property which shadows the prototype property. This is how you can override prototype provided methods. 
  • A constructor, a function called with new, creates an object and sets that object's [[prototype]] property to its prototype property. Thus:

var f=function(){};
f.prototype=proto;
obj=new f();

is the same as

obj=Object.create(proto);

  • The prototype chain can be used to provide methods to a set of objects without incurring the overhead of duplicating the methods. It also means that a change to a prototype object immediately affects all of the objects that make use of it.
  • The built in objects, e.g. array, string and so on, all have their own constructors which have prototype properties which set the prototype chain. You can modify these prototype objects, but many regard this as a bad idea.
  • The prototype chain can be used to implement something that resembles inheritance, but JavaScript has no type hierarchy and no polymorphism.  
  • Objects in JavaScript are just dynamic bags of properties and the prototype object can act as a library of properties and methods for other objects.

 

Just JavaScript 

 There is a newer version of the draft of the book here.

A Radical Look At JavaScript

Contents

  1. JavaScript Isn't Java, or C, or C# ... (Book Only)
  2. In The Beginning Was The Object
  3. The Function Object
  4. How Functions Become Methods
  5. The Object Expression
  6. Object Construction
  7. The Prototype
  8. Type And Non-Type
  9. Constructor And InstanceOf
  10. Duck Testing And Prototype Construction

-Preface-

Most books on JavaScript either compare it to the better known class based languages such as Java or C++ and even go on to show you how to make it look like the one of these.

Just JavaScript is an experiment in telling JavaScript's story "just as it is" without trying to apologise for its lack of class or some other feature. The broad features of the story are very clear but some of the small details may need working out along the way - hence the use of the term "experiment". Read on, but don't assume that you are just reading an account of Java, C++ or C# translated to JavaScript - you need to think about things in a new way. 

Just JavaScript is a radical look at the language without apologies. 

JustJavaScripticon

Related Articles

JavaScript Doesn't Need Class

Javascript Jems - Object Factories, Constructors and Clones

Javascript Jems - A New Take On Objects

Javascript Jems - The Prototype

 

Credits

Many thanks to pelon for improving this article.

 

To be informed about new articles on I Programmer, install the I Programmer Toolbar, subscribe to the RSS feed, follow us on, Twitter, FacebookGoogle+ or Linkedin,  or sign up for our weekly newsletter.

 

Banner


JavaScript Canvas - Fetch API

Working with lower-level data is very much part of graphics. This extract from Ian Elliot's book on JavaScript Graphics looks at how to use typed arrays to access graphic data.



JavaScript Jems - The Inheritance Tax

JavaScript should not be judged as if it was a poor version of the other popular languages - it isn't a Java or a C++ clone. It does things its own way.  In particular, it doesn't do inheritance  [ ... ]


Other Articles

 

espbook

 

Comments




or email your comment to: comments@i-programmer.info

<ASIN:0596805527>

<ASIN:193398869X>

<ASIN:0137054890>

<ASIN:1449381871>

<ASIN:1430230541>



Last Updated ( Sunday, 10 May 2015 )