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.
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.
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.