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