Page 1 of 3 Building a TimeInterval object is not only useful in itself, it also demonstrates how to use objects in JavaScript without pretending that it is a class-based, typed language. Find out how object augmentation replaces inheritance.
JavaScript Data Structures
Contents
- The Associative Array
- The String Object
- The Array object
- Speed dating - the art of the JavaScript Date object
- Doing JavaScript Date Calculations
- A Time Interval Object
- Collection Object
- Stacks, Queue & Deque
- The Linked List
- A Lisp-like list
- The Binary Tree
- Bit manipulation
- Typed Arrays I
- Typed Arrays II
- Master JavaScript Regular Expressions
* First Draft
JavaScript has a built-in Date object which, if you know how it works, can be used to work with not just dates and times but time intervals. However, it is so much nicer to have an object specifically tailored to working with time intervals. In this article we are going to manufacture a new JavaScript object that does just that. Along the way we will look at some interesting techniques
- inheritance as augmentation
- creating an "overloaded" constructor
- identifying the the new object type
The key idea is that we are going to create a special type of Date object that stores the time interval as a number of milliseconds.
If you want to find out about the Date object before reading on see Speed dating - the art of the JavaScript Date object
Augmentation inheritance
JavaScript is not a class-based language. Its objects don't have an assigned type and they are not created from classes which could be used to define a type. The best JavaScript does to define a type is to associate the constructor function used to create any instance of an object. You can generally assume that if an object was created by the same constructor function then it has the same methods and properties. However this said it is better to try to forget the old ways of doing things using class and type hierarchies when working with JavaScript.
For example, if you have an object and you need an object with a few more properties and methods then a class based language would make use of some form of inheritance. JavaScript can to the same job without strict inheritance simply by augmenting the existing object with new methods.
The object augmentation pattern:
- create a factory function for the new object
- use the existing factory function to create an instance of the old object
- use the new factory function to add any additional properties of methods you need and return the augmented instance.
Let's use the augmentation pattern to create a TimeInterval object from the Date object.
Starting TimeInterval
We first need a new factory function for the TimeInterval object:
var TimeInterval=function(){
All this has to do is create and return a Date object:
var obj=new Date();
return obj; }
That is the new factory function is:
var TimeInterval=function(){ var obj=new Date(); return obj; }
Now all we have to do is add the new properties and methods we require for the TimeInterval object. Notice that this is an object factory, rather than a constructor, and you don't have to use the new keyword with it. If you do use the new keyword it doesn't make any difference - it just isn't necessary as the function creates its own object to return rather than relying on the default object.
The overloaded factory function
The first thing that we would like to do is create a factory function that is flexible in the way itinitializes the new object. That is, we would like to be able to write:
- TimeInterval(mill) to initialize the object to ticks milliseconds.
- TimeInterval(h,m,s) to initialize the object to the specified hours, minutes and seconds
- TimeInterval(d,h,m,s) to initialize the object to the specified number of days, hours, minutes and seconds.
- TimerInterval(d,h,m,s,mill) to initialize the object to the specified number of days, hours, minutes, seconds and milliseconds.
In other languages this would be done by overloading the constructor, i.e. by providing a different version of the constructor that depended upon the number and type of parameters specified. JavaScript doesn't do typing and so you can't use overloading. However, this doesn't mean that it can't provide a flexible factory function.
The key to creating a flexible factory function is to work with the arguments array directly to work out what parameters have been specified.
In this case we can do the job with a few if statements:
var TimeInterval=function(){ var d=0, h=0, m=0,s=0,mill=0; if(arguments.length===1){ mill=arguments[0].valueOf(); }; if(arguments.length===3){ h=arguments[0].valueOf(); m=arguments[1].valueOf(); s=arguments[2].valueOf(); } if(arguments.length>=4){ d=arguments[0].valueOf(); h=arguments[1].valueOf(); m=arguments[2].valueOf(); s=arguments[3].valueOf(); } if(arguments.length===5){ mill=arguments[4].valueOf(); }
So depending on the number of arguments we set the variables d, h, m, s and mill accordingly. You might wonder why we use valueOf? The simple reason is that this allows the user to specify any object that has a numerical value. For example without valueOf the statement:
var t=TimeInterval(new Date());
wouldn't be allowed as you are expecting an integer number of milliseconds. However in this case the Date().valueOf() returns an integer value which is the number of milliseconds from the fixed date.
In general in JavaScript you should try to allow the widest possible range of parameter types and attempt to handle them reasonably.
At the end of all of the if statements we have a specification of the time interval in terms of d,h,m,s and mill and we need to convert this into milliseconds and use it to create a Date object:
var t=(((d*24+h)*60+m)*60+s)*1000+mill; var obj=new Date(t); return obj; }
Now the object factory returns a Date object initialized to the correct time interval in milliseconds.
<ASIN:1871962579>
<ASIN:1871962625>
|