Javascript object prototype

The javascript object prototype is javascript’s way of sharing implementation across similar objects, much like the way classes are used to do this in many other languages. Although constructor functions look a lot like classes, javascript does not have a class based object system like C# or Java. Instead it has a prototype based object system.

The main difference between the two types of languages is all about objects and classes. In a class based language there is a clear distinction between the ideas of a class and an object. A class is a template for creating an object and an object is a specific instance of a class. In C# you cannot create an object without instantiating it from a class. Even the most basic object of type Object is instantiated from a class. Once the object is created you cannot make it into a different type of object by adding different properties.

In a prototype based systems there are no classes. All objects are created by adding properties and methods to an empty object or by cloning an existing one. Although a constructor function may look like a class (probably so people from more traditional class based languages would be able to use it), it’s really just a function that knows how to add the right properties and methods to create a particular type of object.

This approach is called prototype-based inheritance because an existing object is used as a template (or a prototype – a typical example) to build other objects. The existing object will be used as a starting point to build the new object but the new object does not have to be exactly the same.

How it works in javascript

Prototypes are implemented in javascript using the prototype property of constructor functions. Any property or method that’s added to the constructor’s prototype automatically becomes part of every object created by that function.

The prototype property is basically a template for the objects created by the constructor. It contains the things that should be the same among all objects created by the constructor. Individual objects can override and change the things they inherit from the constructor’s prototype but they will all start out the same.

The aim of the prototype is to share implementation between similar objects, to make things more convenient for programmers. It is not designed to be a type system. Javascript objects are dynamic so they can be changed after they are created. Knowing that an object was created by a particular constructor function does not guarantee anything about the methods or properties that an object will have.

A simple example

The easiest way to understand this is to look at an example, so let’s take a look at the Pet example again.

All the pets created by the pet constructor function have a sayHello() method. When we created our pet using the constructor function, we created a separate sayHello() function for each pet by creating the function and adding it to the new object we were creating:

  1. function Pet(name, species, hello)
  2. {
  3.     this.name = name;
  4.     this.species = species;
  5.     this.hello = hello;
  6.     this.sayHello = function()
  7.     {
  8.         alert(this.hello);
  9.     }
  10. }

Wouldn’t it be better if there would be just one sayHello() function that all the pet objects will automatically share? To do this we could remove the sayHello() method from the constructor function and add it to the function’s prototype property instead:

  1. function Pet(name, species, hello)
  2. {
  3.     this.name = name;
  4.     this.species = species;
  5.     this.hello = hello;
  6. }
  7.  
  8. Pet.prototype.sayHello = function()
  9. {
  10.     alert(this.hello);
  11. }
  12.  
  13. var rufus = new Pet("Rufus", "cat", "miaow");
  14. rufus.sayHello();

Complete example

When we created the Pet function, its prototype property was automatically set to an empty object. Every function is set up this way when it’s created because there’s no way for javascript to know whether any particular function will be used as a constructor function or not.

We wanted all our pets to have a sayHello method, so we added a sayHello() method to the Pet’s prototype property. The prototype property contains a regular javascript object so this is just the same as assigning a new method or property to any other object. In this case we have created a new anonymous function and assigned it to a property called sayHello.

When we created the rufus object, it automatically maintained an invisible link back to the Pet function that created it. Then when we tried to access the sayHello() method, javascript first looked for a sayHello() method set directly on the rufus object. When it couldn’t find one, it then looked at the Pet constructor’s prototype, found sayHello() and called that instead.

Because the property resolution happens when the property is called, any changes made to the prototype property will be reflected in all of the objects already created by the constructor. Properties can be dynamically added or removed or the prototype could even be replaced with an entirely new object.

This all happens transparently. The code that is using the rufus object doesn’t need to care whether rufus’ sayHello() method was set directly on rufus or if it belongs to the Pet constructor.

The prototype property is just an object

The prototype property is just an object. There’s nothing particularly special or magic about it. Anything you can do to a normal object you can also do to a function’s prototype property. This includes adding and removing properties, accessing the properties through substring (Pet.prototype["property"]) or dot (Pet.prototype.property) notation and iterating through the properties using a for loop.

When a new function is created the prototype property is set to an empty object, exactly the same if we said Pet.prototype = new Object() when we created the function. Javascript does this by default whenever you create a new function to make sure that any objects created by calling the function will automatically get all of the methods and properties that are belong to every Object (like toString()).

In the previous example we just added another property to object that was automatically created. Instead we could have overriden the default empty object with a new one instead:

  1. Pet.prototype = {
  2.     sayHello : function()
  3.     {
  4.         alert(this.hello);
  5.     }
  6. };

You can even set the prototype to an be a new object created by another constructor. This is called prototype chaining and is the way related javascript objects can share implementation much like inheritance in a class based language:

  1. function Cat()
  2. {
  3.     …
  4. }
  5. Cat.prototype = new Pet();

Every constructor has a prototype property

Even built in constructors like String or Array. Libraries like prototype and ASP.NET ajax use this to add functions to the built in types like Array.reverse() or String.trim().

Here’s a simple example that adds a sheep function to all javascript string objects:

  1. String.prototype.sheep = function()
  2. {
  3.     return "baaah " + this;
  4.  
  5.  
  6. }
  7. var hello = "hello world";
  8. alert(hello.sheep());

Complete example.

Why is this important?

The practical reason why this is important is sharing single a method between all objects uses less memory than having a separate copy for each object. This can be a big advantage when working on a complicated web application with lots of objects.

The javascript object prototype also enables you use some interesting coding patterns like inheritance and object cloning to more easily share implementation between similar objects in a similar way to how you would use classes to do this in a class based language.

What’s next?

Prototype chaining is used to build new types of objects based on existing ones. It has a very similar job to inheritance in a class based language.

This article is part of a set of related posts about How javascript objects work.

Posted on 18 Jan 09 by Helen Emerson (last updated on 29 Nov 09).
Filed under Javascript

Comments

ted devito 11 Mar 2009

hi Helen,
I’ve really enjoyed all this info you’ve put together on using JS. You write clearly and break down these concepts into thought chunks I understand. Since I know I am sometimes/often guilty of trying to convey too many concepts at one time, I don’t feel surprised by how common that practice is among coders and instead simply appreciate when I find the contrast.

Anyway, thought you might like to enhance your comment fields with tabs. Makes it easier for us coders to indent our code when we’re discussing.

http://teddevito.com/demos/textarea.html

Helen 12 Mar 2009

Thanks Ted, I’m glad you’ve found it useful. :) The tabs in the comment field is a good idea. I’ll have to look into it!

Sebastian 31 Mar 2009

Hi,
I’m not sure but I thought, that you can’t add methodes to existing classes like “string” or “node” in IE. Tell me if I’m wrong!

Helen 11 Apr 2009

You can extend built in javascript objects like string in all browsers, even IE:

String.prototype.trim = function()
{
alert(“this function can trim a string object”);
}
var moo = “Hello world”;
moo.trim();

In Firefox, Safari, Chrome and Opera you can also extend HTML elements:

window.onload = function()
{
HTMLElement.prototype.moo = function()
{
alert(“Calling the HTML Element’s moo function”);
}
document.body.moo();
}

In IE (I just tested in IE8) you can’t extend the DOM objects because they’re not part of javascript, they’re really COM objects.

You can see the full example here: http://helephant.com/wp-content/uploads/2009/01/built-in-prototype.html

Helen 14 Apr 2009

Ah ha! You can also extend the prototype of DOM objects in IE8: http://msdn.microsoft.com/en-us/library/dd282900(VS.85).aspx

John Middlemas 16 Jun 2009

Using Pet.prototype.sayHello= as opposed to this.sayHello= in the Pet example makes no difference to the end result and it is simpler to use this.sayHello=. Your justification for the former is saving memory but I wonder if that is important these days. Why complicate the matter further when programming is complicated enough already.

I also wonder if using Pet.prototype.sayHello= does actually save memory. I tested the rufus object on my system and it still included the sayHello method even if Pet.prototype.sayHello= was used.

Starrow Pan 13 Nov 2009

Appreciate your article that make me capable of appreciating the simplicity and ingenuity of the design of javascript.
@John,
At least per my experiment in Firebug js console, prototype is shared to all instances.
I think another advantage of prototype is it exhibits the dynamic essence of javascript. Of course you can declare properties and functions with a constructor, but prototype enable you modify the common behavior of a ‘class’ of objects LATER.

Ron 23 Nov 2009

To John Middlemas:

The Pet.prototype.sayHello example is simplistic to illustrate the idea. In the real world, javascript classes are much more significant in size, and can have rather large methods. If I have 1000 instances of an object, without prototype I would have 1000 instances of that large method as well. With prototype, the sayHello method will be included but only as a reference to the single existing method, which translates to a significant reduction in memory usage.
I’m all for simplified programming, but would have to defend prototype as a necessity.

helen 23 Nov 2009

I also think that whether you want to use prototypes or not, it’s good to understand what they are so you can make an informed choice and so you can understand what other people’s code is doing.

I think it’s particularly helpful if you are using a Javascript library because many of them use prototypes to simulate classic inheritance and if things go wrong it’s really hard to debug without understanding what’s going on.

That said.. I should update my article with a more convincing argument in the object prototype’s favour. :)

John F. 14 Nov 2010

Thanks for the lucid article. It helped me assure myself I was right when I was puzzling over some javascript.

Furqan Shakoor 09 Jan 2012

You ma’am , are awesome. I have been looking for good javascript knowledge but all I could find was “How to create slideshows” ,”How to show alerts” and this kind of immature stuff. I started reading Douglas Crockford’s “Javascript – The good parts”, it is an amazing book. I just needed clarification for prototypes and constructors and your articles were are a great help.
Thank You

Vineet Gupta 30 Jan 2012

Hi Helen,
Very well done JS object prototype article. Keep up the good work.

Terral Lewis 13 Aug 2012

What is the difference between constructor prototypes and object prototypes and how should they be used? Also, what are the pros and cons of both?

Thanks!

Helen Emerson 19 Aug 2012

A constructor function has instructions in it to create a new object. It’s basically a little object factory. In more traditional class-based languages like Java, this is mostly done declaratively by creating a class and declaring what methods and properties it has. In javascript, it’s done by taking an empty object and assigning properties and methods to it.

Any object created with a constructor function retains a special link back to the constructor function that created it through the object prototype. You can use the object prototype to assign properties and methods to all objects that were created by the constructor. Rather than needing to create a new bark() method for all your dog objects when you create them in the Dog constructor function, you can just add the bark() method to the object prototype and all objects created with the Dog constructor will be able to bark().

The most powerful thing about the object prototype is if you want to chain them. This means that you create your constructor’s object prototype using another constructor function. For example if say Dog.prototype = new Animal(), the dog objects will automatically get all of the methods and properties of the animal constructor’s object prototype. This is how to do inheritance in javascript.

The other thing to take into account is if you create the function new each time in your constructor function (rather than reusing the same function object each time) you may run into memory problems if your javascript code has a lot of objects. This is usually only a problem in really large scale javascript, such as if you were creating a javascript framework. The object prototype doesn’t have this problem because all of the objects use the same instance of the function.

Otherwise most of the time it doesn’t matter which method you use to set up your object. It’s a matter of style. Setting things up explicitly in a constructor function is a bit easier to follow.

José.A 13 Sep 2012

Nice article. Thanks for your effort.
Only thing I haven’t been able to test, is the part when you say the prototype can be completely replaced with an entirely new object.

I have:
function Pet(){
// whatever
}

var myPet = new Pet();
Pet.prototype = {eat:”almost everything”};

alert(myPet.eat);

And the alert returns ‘undefined’. So, unless my code is wrong, how can I completeley change the prototype of an object?

Thank you in advance

Trackbacks