Using Prototype Property in JavaScript

by Stoyan Stefanov | August 2008 | AJAX Web Development

In this article by Stoyan Stefanov, you'll learn about the prototype property of the function objects. Understanding how the prototype works is an important part of learning the JavaScript language. After all, JavaScript is classified as having a prototype-based object model. There's nothing particularly difficult about the prototype, but it is a new concept and as such may sometimes take some time to sink in. It's one of these things in JavaScript (closures are another) which, once you "get" them, they seem so obvious and make perfect sense. As with the rest of the article, you're strongly encouraged to type in and play around with the examples; this makes it much easier to learn and remember the concepts.

The following topics are discussed in this article:

  • Every function has a prototype property and it contains an object
  • Adding properties to the prototype object
  • Using the properties added to the prototype
  • The difference between own properties and properties of the prototype
  • __proto__, the secret link every object keeps to its prototype
  • Methods such as isPrototypeOf(), hasOwnProperty(), and propertyIsEnumerable()

The prototype Property

The functions in JavaScript are objects and they contain methods and properties. Some of the common methods are apply() and call() and some of the common properties are length and constructor. Another property of the function objects is prototype.

If you define a simple function foo() you can access its properties as you would do with any other object:

>>>function foo(a, b){return a * b;}
>>>foo.length

2

>>>foo.constructor

Function()

prototype is a property that gets created as soon as you define the function. Its initial value is an empty object.

>>>typeof foo.prototype

"object"

It's as if you added this property yourself like this:

>>>foo.prototype = {}

You can augment this empty object with properties and methods. They won't have any effect of the foo() function itself; they'll only be used when you use foo()as a constructor.

Adding Methods and Properties Using the Prototype

Constructor functions can be used to create (construct) new objects. The main idea is that inside a function invoked with new you have access to the value this, which contains the object to be returned by the constructor. Augmenting (adding methods and properties to) this object is the way to add functionality to the object being created.

Let's take a look at the constructor function Gadget() which uses this to add two properties and one method to the objects it creates.

function Gadget(name, color) { 
  this.name = name;
  this.color = color;
  this.whatAreYou = function(){
   return 'I am a ' + this.color + ' ' + this.name;
  }
}

Adding methods and properties to the prototype property of the constructor function is another way to add functionality to the objects this constructor produces. Let's add two more properties, price and rating, and a getInfo() method. Since prototype contains an object, you can just keep adding to it like this:

Gadget.prototype.price = 100;
Gadget.prototype.rating = 3;
Gadget.prototype.getInfo = function() {
  return 'Rating: ' + this.rating + ', price: ' + this.price;
};

Instead of adding to the prototype object, another way to achieve the above result is to overwrite the prototype completely, replacing it with an object of your choice:

Gadget.prototype = { 
  price: 100,
  rating: 3,
  getInfo: function() {
   return 'Rating: ' + this.rating + ', price: ' + this.price;
  }
};

Using the Prototype's Methods and Properties

All the methods and properties you have added to the prototype are directly available as soon as you create a new object using the constructor. If you create a newtoy object using the Gadget() constructor, you can access all the methods and properties already defined.

>>> var newtoy = new Gadget('webcam', 'black');
>>> newtoy.name;

"webcam"

>>> newtoy.color;

"black"

>>> newtoy.whatAreYou();

"I am a black webcam"

>>> newtoy.price;

100

>>> newtoy.rating;

3

>>> newtoy.getInfo();

"Rating: 3, price: 100"

It's important to note that the prototype is "live". Objects are passed by reference in JavaScript, and therefore the prototype is not copied with every new object instance. What does this mean in practice? It means that you can modify the prototype at any time and all objects (even those created before the modification) will inherit the changes.

Let's continue the example, adding a new method to the prototype:

Gadget.prototype.get = function(what) { 
  return this[what];
};

Even though newtoy was created before the get() method was defined, newtoy will still have access to the new method:

>>> newtoy.get('price');

100

>>> newtoy.get('color');

"black"

Own Properties versus prototype Properties

In the example above getInfo() used this internally to address the object. It could've also used Gadget.prototype to achieve the same result:

Gadget.prototype.getInfo = function() { 
  return 'Rating: ' + Gadget.prototype.rating + ', price: ' + Gadget.prototype.price;
};

What's is the difference? To answer this question, let's examine how the prototype works in more detail.

Let's again take our newtoy object:

>>> var newtoy = new Gadget('webcam', 'black');

When you try to access a property of newtoy, say newtoy.name the JavaScript engine will look through all of the properties of the object searching for one called name and, if it finds it, will return its value.

>>> newtoy.name

"webcam"

What if you try to access the rating property? The JavaScript engine will examine all of the properties of newtoy and will not find the one called rating. Then the script engine will identify the prototype of the constructor function used to create this object (same as if you do newtoy.constructor.prototype). If the property is found in the prototype, this property is used.

>>> newtoy.rating

3

This would be the same as if you accessed the prototype directly. Every object has a constructor property, which is a reference to the function that created the object, so in our case:

>>> newtoy.constructor

Gadget(name, color)

>>> newtoy.constructor.prototype.rating

3

Now let's take this lookup one step further. Every object has a constructor. The prototype is an object, so it must have a constructor too. Which in turn has a prototype. In other words you can do:

>>> newtoy.constructor.prototype.constructor

Gadget(name, color)

>>> newtoy.constructor.prototype.constructor.prototype

Object price=100 rating=3

This might go on for a while, depending on how long the prototype chain is, but you eventually end up with the built-in Object() object, which is the highest-level parent. In practice, this means that if you try newtoy.toString() and newtoy doesn't have an own toString() method and its prototype doesn't either, in the end you'll get the Object's toString()

>>> newtoy.toString()

"[object Object]"

Overwriting Prototype's Property withOwn Property

As the above discussion demonstrates, if one of your objects doesn't have a certain property of its own, it can use one (if exists) somewhere up the prototype chain. What if the object does have its own property and the prototype also has one with the same name? The own property takes precedence over the prototype's.

Let's have a scenario where a property name exists both as an own property and as a property of the prototype object:

function Gadget(name) { 
  this.name = name;
}
Gadget.prototype.name = 'foo';

"foo"

Creating a new object and accessing its name property gives you the object's ownname property.

>>> var toy = new Gadget('camera');
>>> toy.name;

"camera"

If you delete this property, the prototype's property with the same name"shines through":

>>> delete toy.name;

true

>>> toy.name;

"foo"

Of course, you can always re-create the object's own property:

>>> toy.name = 'camera';
>>> toy.name;

"camera"

 

Sign up for a Packt account to see the rest of this article

Now that you've read a few articles, you might want to consider signing up for a Packt account. It takes a matter of seconds, will give you access to all the articles on PacktPub.com, and once you've signed up you'll be returned here to carry on reading your article.

Furthermore, you'll gain access to nine free ebooks, and be offered a free trial of PacktLib, Packt's online library. Simply enter your details here, or log in to your existing account.

Log in

...or register

Great Article by
Thanks man this helped a lot!
Thanks! by
This really helped me with js prototyping, thanks!
very good explanation by
thx for this one
Thanks for a great tut but the second half... by
Thanks for a great tutorial on this topic. I have been going through the codes and like Mithun I also get different outputs. For 'newtoy.constructor' I get 'function Object() { [native code] }' For 'newtoy.constructor.prototype.rating' I get 'undefined' and so on. I used ff4.0. Does anyone know anything about this issue?
Excellent Tutorial. However, by
Excellent Tutorial. However, I faced some problems while executing the code snippets mentioned in the article. NOt sure if I am doind something wrong..... I tested in Firefox 3.6.13 Whenever I do a newtoy.constructor, it prints out Object() in the console log. Also, the prototype property is not accessible using newtoy.constructor.prototype.price printts out undefined. If I treplace newtoy with the word Gadget, thigs seem to print fine. Regards Mithun
Excellent by
It explained the topic very well
Good Stuff! by
Thanks, I Learned a lot!
Great by
Thank's for a comprehensive tutorial!
Thank's by
Very nice indeed! Not much interesting information in the web. But this is one is comprehensive!
Congratulations by
Very good article....

Post new comment

Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Sort A-Z