-->
Bookmark and Share

Calendar

See the demo page for the finished version of the code.

Extending the Date Object

One of the most useful features of JavaScript is the ability to add and remove properties and methods to ant given object at run time. We'll use this feature to extend the predefined Date object.

To add a property to an instance of an object, you simply set a value for it. Likewise, to add a method you simply assign a function to it. Below is an example.

var myDate  = new Date();
var myDate2 = new Date();

// Add a new property and a new method to myDate.

myDate.monthNames = new Array("January", "February", "March", "April",
  "May", "June", "July", "August", "September", "October", "November",
  "December");
myDate.getMonthName = myGetMonthName;

// Function for the getMonthName() method.

function myGetMonthName() {

  return this.monthNames[this.getMonth()];
}

Unfortunately, only one particular instance of the Date object (the variable myDate) is assigned the new property and method. Any other Date objects created in the script (like myDate2) are unaffected. You can see this for yourself using the links below.

Show myDate.getMonthName() | Show myDate2.getMonthName()

Calling myDate2.getMonthName() will generate a JavaScript error. That's because the getMonthName() method was assigned to myDate but not to myDate2. To understand why this happens you need to understand the way JavaScript views objects.

Class vs. Prototype

In most other object-oriented programming languages, like C++ or Java, object types are defined using classes. Within a class definition you define the properties and methods for a particular object type along with the the code to implement each method.

You generally create a new instance of an object using the new operator which calls the class constructor function. For example, in C++:

String s;

s = new String("Hello world!");
cout << s << endl;

Note that the variable s is declared as a String object. You could not use that variable (within the same scope) for any other object type. This is where JavaScript differs from most other languages.

var s;

s = new String("John");
alert("Hello " + s);
s = new Array(5, 9, 7, 2, 3);
alert(s[2]);

Here, s is declared simply as a variable (the var keyword). It is first assigned a String object as its value and can therefore be used in string expressions. But then it is reassigned to an Array object and can then be used as such. Try that in C++ and the program won't even compile.

In effect, s is just an arbitrary object. Its properties and methods are assigned at run time when it is given an object value. That's also why you can add properties and methods to an individual instance of an object. You're not adding the property or method to a class definition and therefore, to all objects of that class, just to a single instance of the object.

But how does JavaScript know what properties and methods to give an object if there is no class definition for it? For that, JavaScript uses object prototyping.

Object Prototypes

A prototype is a kind of template. All predefined JavaScript objects like Array or String have such a template. So their properties and methods are automatically set whenever a new instance of the object is created.

You can then add new properties or methods to the object instance, but they apply only to that single instance, as seen above. Both myDate and myDate2 were assigned a Date object as a value, and were given the predefined properties and methods associated with that object.

But myDate was then given a new property and a new method and only myDate could use them. For myDate2 they are undefined and trying to use them generates an error. To give myDate2 the same new property and method, you'd have to explicitly assign that same property and method (and their values) to the myDate2 variable as well.

myDate2.monthNames = new Array("January", "February", "March", "April",
  "May", "June", "July", "August", "September", "October", "November",
  "December");
myDate2.getMonthName = myGetMonthName;

This could obviously become tedious if you plan to use a number of such variables.

Constructor Functions and Prototypes

When you create your own object in JavaScript, you typically create a constructor function for it.

function Rectangle(w, h) {

  // Properties

  this.width  = w;
  this.height = h;

  // Methods

  this.getArea = RectangleGetArea;
}

function RectangleGetArea() {
  return this.width * this.height;
}

var r1 = new Rectangle( 10,  20);
var r2 = new Rectangle( 75,  55);
var r3 = new Rectangle(150, 100);

alert(r2.getArea());

In this case, your constructor function does the job of assigning the same base set of properties and methods to each new instance of the object. To change those properties or methods, you just change the constructor function.

But what if you want to add properties or methods to a predefined object like Date? You don't have access to the object's constructor function. But you can access its prototype.

var myDate  = new Date();
var myDate2 = new Date();

// Add a new property and a new method to the Date object.

Date.prototype.monthNames = new Array("January", "February", "March",
  "April", "May", "June", "July", "August", "September", "October",
  "November", "December");
Date.prototype.getMonthName = myGetMonthName;

...

var myDate3 = new Date();

Date.prototype refers to the template for the predefined Date object. Tacking on the property or method name and a value causes JavaScript to apply them to every instance of that object. That includes every instance that has already been defined, and any new ones as well. So in the above, myDate3 also gets the new property and method.

With languages like C++ or Java, you can extend an existing object by creating a new class based on the existing one. You can then add your own properties and methods to the ones inherited from the base class.

However, you would then have two distinct classes. Using prototypes in JavaScript has the effect of changing the base class itself.

This ability to dynamically add properties and methods to any existing object type through prototyping allows us to easily expand on any object, whether it's user-defined or predefined.