Summary
JavaScript sports a number of built-in objects that extend the flexibility of the language. These objects are Date, Math, String, Array, and Object. Several of these objects are "borrowed" from the Java language specification, but JavaScript's implementation of them is different. If you're familiar with Java, you'll want to carefully examine JavaScript's built-in object types to avoid any confusion. (4,200 words)
Topic Links: |
The JavaScript object model is a simple one. The bulk of these objects deal with window content -- documents, links, forms, and so forth. In addition to window-content objects, JavaScript supports a small handful of "built-in" objects. These built-in objects are available regardless of window content and operate independently of whatever page Netscape has loaded.
The built-in objects are Date, Math, String, Array, and Object. Each is used in a unique and not-quite-consistent way. Furthermore, newer versions of JavaScript (as found in Netscape "Atlas," currently in beta) implement several of these objects in a different manner than in Netscape 2.0. In this column we will address these built-in objects and how to use them. And we'll make note of the quirks you'll encounter as you apply these objects to your JavaScript pages.
Understanding the string object
Of all JavaScript's objects, the String object is the most commonly used. In the Netscape 2.0 JavaScript implementation, new string objects are created implicitly using a variable assignment. For example,
var myString = "This is a string";creates a string, with the specified text, called
myString.
In Netscape 2.0, there is no actual object called string, and attempting to instantiate a new String object using the new statement results in an error, as String (or string) is not a defined keyword. In the Atlas version of Netscape, however, String is a bona fide object, and the String keyword can be used to create new strings. The following two approaches are allowed in Atlas, but not in Netscape 2.0.
var myString = new String(); myString = "This is a string";and
var myString = new String ("This is a string");String objects have one property: length. The length property returns the length of the string and uses the syntax
string.length,
where string is the name of the string variable. Both of the following display 16.
alert ("This is a string".length)and
var myString = "This is a string"; alert (myString.length);While there may be just one string property, JavaScript supports a large number of methods that can be used with strings. These methods can be roughly divided into two broad camps: string management and text format.
String management methods include substring
, indexOf
, lastIndexOf
, and toLowerCase
. These are used to return or change the content of the string in some way. For instance, the substring method returns a specified portion of a string. The indexOf method determines the location of a character or group of characters in a string. And the toLowerCase method converts the string to lower case. (As you can imagine, there's also a toUpperCase
method.)
Text format methods are used to format text in a document in some special way, and are provided as alternatives to using HTML tags for the same purpose. These methods include big, small, sup, sub, anchor, link, and blink.
String methods can be used directly on strings, or on variables that contain strings. Methods always use open and closed parentheses, even if the method doesn't use parameters. For instance, to convert text to upper case, you'd use one of the following:
var tempVar = "this text is now upper case".toUpperCase();or
var myString = "this text is now upper case"; var tempVar = myString.toUpperCase();In Netscape 2.0 there is only one String object, and all strings are created from it. Conversely, strings are first-class objects in Atlas, and each new string is a treated as a separate object. The single-object behavior of strings in Netscape 2.0 can cause some subtle side effects. Take the short script segment that follows. Two strings are created:
string1
and string2
. A new property (called extra) is assigned to string1. Yet the alert message shows that the property also now belongs to string2.
<SCRIPT> string1 = "this is string 1" string2 = "this is string 2" string1.extra = "new property" alert (string2.extra) </SCRIPT>Technically speaking, strings are "immutable" in JavaScript. That is, the content of the string is static, and cannot be changed. In Netscape 2.0, JavaScript is capable of modifying a string only by creating a new location in memory for it. Because of this, a script that modifies a string many times is prone to memory errors. Each time the string is altered, JavaScript creates a new location in memory for the new version. New strings are created before garbage collection takes place to destroy the old string. Eventually, JavaScript uses all of its available memory, and an "out of memory" error occurs.
A classic example of this problem can be seen in the popular JavaScript "message scrollers," where a message scrolls in the status bar or a text box. For each pass, the scroller redefines the string variable that is displayed. Memory is eventually depleted because JavaScript creates new instances of the string with each pass. For example, the following script will eventually (sooner on some platforms, such as Windows 3.1) cause an "out of memory" error:
<SCRIPT> var count = 0; var text = "This is a test of a JavaScript scroller. "; scroll(); function scroll () { var myString = text.substring (count, text.length) + text.substring (0, count) window.status = myString if (count < text.length) count ++; else count = 0; setTimeout ("scroll()", 333); // 333ms is the minimum delay for Netscape 2.0 } </SCRIPT>A simple rewrite avoids the problem of creating new blocks of memory. Delete the myString variable assignment, and parse the text directly to the status bar, using window.status. See the revised JavaScript scroller to view the script in action. (Watch the status bar to see the text scroll by.)
window.status = text.substring (count, text.length) + text.substring (0, Count)(While the above approach avoids JavaScript's string-object replication problem, memory leaks still occur because of the use of the
setTimeout method
. Over many iterations -- typically several thousand or more -- setTimeout will consume all available memory, and eventually JavaScript will display an "out of memory" message.)
For your reference, here are the methods and properties used with JavaScript's string object:
length | The length of a string |
String Methods
anchor | Creates a named anchor (hypertext target) |
big | Sets text to big |
blink | Sets text to blinking |
bold | Sets text to bold |
charAt | Returns the character at a specified position |
fixed | Sets text in fixed-pitch font |
fontcolor | Sets the font color |
fontsize | Sets font size |
indexOf | Returns the first occurrence of character x starting from position y |
italics | Sets text to italics |
lastIndexOf | Returns the last occurrence of character x starting from position y |
link | Creates a hyperlink |
small | Sets text to small |
strike | Sets text to strikeout |
sub | Sets text to subscript |
substring | Returns a portion of a string |
sup | Sets text to superscript |
toLowerString | Converts a string to lowercase |
toUpperString | Converts a string to uppercase |
Using JavaScript as a Scientific Calculator
JavaScript's Math object provides advanced arithmetic and trigonometric functions, expanding on JavaScript's basic arithmetic operators (plus, minus, multiply, divide). The Math object in JavaScript is borrowed from Java. In fact, the implementation of the Math object in JavaScript closely parallels the Math class in Java, except that the JavaScript Math object offers fewer methods.
JavaScript's Math object properties are treated as constants. In fact, the property names are in all upper-case, following the usual convention of capitalizing variable constants. These properties return often-used values, including pi and the square root of 2. The Math methods are used in mathematical and trigonometric calculations. Handy Math-object methods include ceil, floor, pow, exp (exponent), max, min, round, and random. (Random is only available when using the X Window platform, however.)
The Math object is static, so you don't need to create a new Math object in order to use it. To access the properties and method of the Math object, you merely specify the Math object, along with the method or property you wish. For example, to return the value of pi, you use:
var pi = Math.PI;Similarly, to use a math method you provide the name of the method, along with the parameters you wish to use. For example, to round the value of pi, you'd use:
var pi = Math.PI; var pieAreRound = Math.round(pi); // displays 3Note that you must specify the Math object by name for each Math method/property you wish to use. JavaScript does not recognize the keywords PI and round all by themselves. Exception: you may use the
with
statement to associate the names of methods and properties with the Math object. This technique is a handy space-saver when you must use several Math properties and methods. The previous example can be written as
with (Math) { var pi = PI; var pieAreRound = round(pi); alert (pieAreRound) }For your reference, here are the properties and methods supported by JavaScript's Math object.
E | Euler's constant |
LN2 | The natural logarithm of 2 |
LN10 | The natural logarithm of 10 |
LOG2E | The base 2 logarithm of e |
LOG10E | The base 10 logarithm of e |
PI | The numeric equivalent of PI: 3.14 etc. |
SQRT1_2 | The square root of one-half |
SQRT2 | The square root of 2 |
Math Methods
abs | Returns the absolute value of a number |
acos | Returns the arc cosine of a number |
asin | Returns the arc sine of a number |
atan | Returns the arc tangent of a number |
ceil | Returns the least integer greater than or equal to a number |
cos | Returns the cosine of a number |
exp | Returns e (Euler's constant) to the power of a number |
floor | Returns the greatest integer less than or equal to its argument |
log | Returns the natural logarithm (base e) of a number |
max | Returns the greater of two values |
min | Returns the lesser of two values |
pow | Returns the value of a number times a specified power |
random | Returns a random number (X-platforms only) |
round | Returns a number rounded to the nearest whole value |
sin | Returns the sine of a number |
sqrt | Returns the square root of a number |
tan | Returns the tangent of a number |
Asking JavaScript for a Date
Also borrowed by Java is the Date object, which can be used in JavaScript to determine the current time and date. A popular JavaScript application of the Date object is displaying a digital clock in a text box. The script uses the Date object to update the clock once every second. You also use the Date object to perform date math. For example, your script might determine the number of days between now and a certain future date. You can use this to display a "countdown," such as the number of days left of your company's big sale.
JavaScript treats the Date object like a constructor class. To use Date you must create a new Date object; you can then apply the various Date methods to get and set dates. (The Date object has no properties.) If you're familiar with the Date class in Java, you'll find the properties of the JavaScript Date object largely the same. The most commonly used methods are the get
methods, which obtain the time and date of the value in the Date object. These methods are:
Constructing a new Date object can take several forms. To return an object containing the current date and time, you use the Date object without parameters. In the following, date_obj
is a new object, containing the value of the current date and time, as set by the computer's system clock.
var date_obj = new Date();Alternatively, you can specify a given date and time as part of the date constructor. Either of these methods is allowed -- both set the new date object to January 1, 1997, at midnight local time.
var date_obj = new Date ("January 1 1997 00:00:00")and
var date_obj = new Date (97, 0, 1, 12, 0, 0)To use a Date method, append the method to the date object you previously created. For example, to return the current year, use:
var now = new Date(); var yearNow = now.getYear();For your reference, here are the methods supported by JavaScript's Date object.
getDate | Returns the day of month of a specified date |
getDay | Returns the day of week of a specified date |
getHours | Returns the hour of a specified date |
getMinutes | Returns the minutes of a specified date |
getMonth | Returns the month of a specified date |
getSeconds | Returns the seconds of a specified date |
getTime | Returns the number of seconds between January 1, 1970 and specified date |
getTimeZoneoffset | Returns the time zone offset in minutes for the current locale |
getYear | Returns the year of specified date |
parse | Returns the number of milliseconds in a data since January 1, 1970, 00:00:00 |
setDate | Sets the date |
setHours | Sets the hours of a specified date |
setMinutes | Sets the minutes of a specified date |
setMonth | Sets the month of a specified date |
setSeconds | Sets the seconds of a specified date |
setTime | Sets the time of a specified date |
setYear | Sets the year of a specified date |
toGMTString | Converts a date to a string using GMT conventions |
toLocaleString | Converts a date to a string using locale conventions |
toString | Converts the value of a Date object or current location object to a string |
UTC | Converts a comma-delimited date to the number of seconds since Jan 1, 1970 |
Date Gotchas
While the Date object is fairly straightforward to use, it does suffer some bugs, including a few that will cause Netscape to crash. Keep the following in mind when working with dates.
Macintosh is one day in the future
In the Macintosh version of Netscape 2.0, the Date object is off by one day in the future. You can compensate for this by subtracting a day, using a technique such as
now.setDate(now.getDate()-1);You must be careful that you subtract the day for Macintosh users only, and only if they are using Netscape 2.0. (This bug is gone in Atlas.) You can use the
navigator.userAgent
property for this, but an easier approach is
var testForMac = new Date(0); // start of JavaScript epoch: Jan 1, 1970 if (testForMac == 86400000) now.setDate(now.getDate()-1);
Dates before 1970 can crash Netscape
A natty bug in most platforms of Netscape 2.0 -- and in the beta versions of Atlas -- causes an unceremonious crash if you attempt you use a date prior to January 1, 1970. You can avoid the bug if you remember to always specify dates of 1970 and beyond. The issue isn't so easily dismissed if you allow user entry of dates. At the very least, if you allow the user to type the year as text, you will need to first verify that the year is 1970 or beyond. This can be done with a simple if
expression (in the following, the userDate
variable contains the year typed by the user):
if (parseInt(userDate) < 1970) // invalid year else // valid year
Specify numeric values for dates after 1999
Similar to the pre-1970 date bug, Netscape can crash if you provide a string value for any date beyond 1999. However, no crash results if you use numeric values for the date, instead of a string. For example, the first line below causes a crash, but the second one does not:
date_obj = new Date ("January 1, 2000"); // crashes Netscape date_obj = new Date ("100, 0, 1"); // does not crash Netscape
Creating Objects and Arrays
JavaScript supports two (currently) undocumented object constructors: Array and Object. Both do a similar job, but are used in different situations. In JavaScript, an array is really just an object, using numbers or associative names for the array elements. You can create new arrays and objects with either constructor, but for readability, you'll probably want to use the constructor that is most closely associated with your application. Use Array when creating an array; use Object when creating an object.
Let's tackle the Array constructor first.
In JavaScript you can create an array explicitly using your own constructor function. Here is an example of a basic array constructor.
function makeArray(numElements) { this.length = numElements for (count = 1; count <= numElements; count++) this[count] = 0; return (this); }To define a new array, you call the
makeArray
function using the new statement. The following example creates an array with three elements, and fills them with data.
var myArray = new makeArray(3); myArray[1] = "item 1"; myArray[2] = "item 2"; myArray[3] = "item 3";Actually, JavaScript doesn't much care how you make your arrays. Though you can define the number of elements in the array, the
makeArray
function uses this value only to pre-load an initial value in the first three elements. (Element 0 contains the length of the array; element[0] is synonymous with the length property.) You can add additional elements at any time, even after the array has been created.
The Array object in JavaScript does the same work as the makeArray
constructor function. You can use it to create a new array, then provide the data for each element in the usual manner. In Netscape 2.0, the Array object ignores any "length" or number of elements value you pass to it, so if you need to store the number of elements in the array, you must do so explicitly.
var myArray = new Array(); myArray[0] = 3; myArray[1] = "item 1"; myArray[2] = "item 2"; myArray[3] = "item 3";When the array is created, JavaScript merely creates an object for it, but doesn't fill any of the elements with an initial value. JavaScript returns null when you access an element of an array that has not been expressly defined. In the example above myArray[4] returns null, since element[4] is not defined.
In Atlas, the Array object accepts a length parameter, so you don't need to set the length separately. Merely pass the number of elements as a parameter of the Array()
constructor; you may then refer to the length using the construct array_name.length
. You can remove array elements by defining them with null, but the length property remains constant. You can, however, manually change the length property at any time yourself, simply by defining a new value for array_name.length
. As in Netscape 2.0, undefined array elements contain a null value.
Object is a generic object constructor, and is borrowed from Java. However, JavaScript's Object is a much simplified version of the Java Object class. In Java, Object is used as a superclass, but in JavaScript, Object is used as a simplified means of creating new objects without providing an object constructor function. In JavaScript, an object constructor function is called with the new statement, and the function defines any properties or methods of the object. In the following simplified example, the calling statement instantiates a new object named myObject. The makeObject
function creates the object, defining one property ("name") to it.
myObject = new makeObject ("my object"); function makeObject(name) { this.name = name; return (this); }The Object constructor saves you the trouble of making a constructor function, and is handy when you don't need or want to define methods and properties of the object when it is created, or when you want to define just one two properties. These following two lines replicate the example above:
myObject = new Object(); myObject.name = "my object";You might use the Object constructor as a quick means to create an object. One such example is a color database, which uses JavaScript as a miniature database. The database can consist of just one or two objects; separate properties of the objects contain the individual data items.
The following script uses JavaScript to built a small database lookup application. The Object constructor creates two objects: an index object and a data object. The index object is really an array with 10 elements; each element contains the name of a Netscape-supported color. The data object mirrors the sequence of the color names, and includes the equivalent hexadecimal value for that color -- the color aliceblue is f0f8ff, for example, and blanchedalmond is ffebcd. Note that the same database can be constructed using Array.
<HTML><HEAD> <TITLE>Color Database</TITLE> <SCRIPT LANGUAGE="JavaScript"> Idx = new Object(); Data = new Object(); Idx[0]=10 Idx[1]="aliceblue" Idx[2]="antiquewhite" Idx[3]="aqua" Idx[4]="aquamarine" Idx[5]="azure" Idx[6]="beige" Idx[7]="bisque" Idx[8]="black" Idx[9]="blanchedalmond" Idx[10]="blue" Data[1]="f0f8ff" Data[2]="faebd7" Data[3]="00ffff" Data[4]="7fffd4" Data[5]="f0ffff" Data[6]="f5f5dc" Data[7]="ffe4c4" Data[8]="000000" Data[9]="ffebcd" Data[10]="0000ff" function checkDatabase() { var Found = false; var Item = document.testform.color.value.toLowerCase(); for (Count = 1; Count <= Idx[0]; Count++) { if (Item == Idx[Count]) { Found = true; alert ("The hex triplet for '" + Item + "' is #" + Data[Count]); break; } } if (! Found) alert ("Sorry, the color '" + Item +"' is not listed in the database."); } </SCRIPT> <FORM NAME="testform" onSubmit="checkDatabase()"> Specify a color name, then click the "Find" button to see its hex triplet: <BR> <INPUT TYPE="text" NAME="color" Value="" onClick=0> <P> <INPUT TYPE="button" NAME="button" Value="Find" onClick="checkDatabase()"> </FORM> </BODY></HTML>JavaScript's associative arrays can come in handy when creating databases. Associative array names are synonymous with the object's property names. With this feature you can simplify the color database script by defining a single object -- named Idx -- for the colors. Then use the names of the colors as the property names, defined as Idx["colorname"]. Each property is assigned the equivalent hexadecimal color value. For example, the property Idx["aliceblue"] -- which is the functional equivalent to the syntax Idx.aliceblue -- is assigned the hex value f0f8ff.
In the revised color database example, the user types a color name, which doubles as a property name for the Idx object. An if
expression determines whether the Idx object contains a property with that name. If the return value is "<undefined>" then no such property exists, and therefore the color is not listed in the database. If the value is something else, it is assumed to be the hex value of the specified color, and that value is displayed in an alert box.
<HTML> <HEAD> <TITLE>Another Color Database</TITLE> <SCRIPT LANGUAGE="JavaScript"> Idx = new Object(); Idx["aliceblue"] = "f0f8ff" Idx["antiquewhite"] ="faebd7" Idx["aqua"] ="00ffff" Idx["aquamarine"] ="7fffd4" Idx["azure"] ="f0ffff" Idx["beige"] ="f5f5dc" Idx["bisque"] ="ffe4c4" Idx["black"] ="000000" Idx["blanchedalmond"] ="ffebcd" Idx["blue"] ="0000ff" function checkDatabase() { var Item = document.testform.color.value.toLowerCase(); if ("" + Idx[Item] == "<undefined>") alert ("Sorry, the color '" + Item +"' is not listed in the database."); else alert (Idx[Item]) } </SCRIPT> <FORM NAME="testform" onSubmit="checkDatabase()"> Specify a color name, then click the "Find" button to see its hex triplet: <BR> <INPUT TYPE="text" NAME="color" Value="" onClick=0> <P> <INPUT TYPE="button" NAME="button" Value="Find" onClick="checkDatabase()"> </FORM> </BODY></HTML>
Conclusion
At first blush, JavaScript's army of objects can be dizzying. But many of these objects are highly specialized, and seldom used in a the typical JavaScript application. JavaScript's built-in objects are a different breed. Because they do not depend on the content of any given page, JavaScript's built-in objects -- Date, Math, String, Array, and Object -- tend to be heavily used in most any script. Mastery of these objects goes a long way to writing the coolest JavaScript applications possible.
About the author
Gordon McComb is an author, consultant, and lecturer. He has written 50 books and over a thousand magazine articles during his 20 years as a professional writer. More than a million copies of his books are in print. Gordon also writes a weekly syndicated newspaper column on computers, reaching several million readers worldwide. Gordon's latest book is The JavaScript Sourcebook, forthcoming from Wiley Computer Publishing. He can be reached at
gordon.mccomb@javaworld.com.