Designers of friendly scripting languages might have nonprogrammers in mind when they first define the scope of their languages, but it's difficult for any such language to be taken seriously by professional programmers unless some of the nerdy basics are there. Math may be anathema to scripters not schooled in computer science, but even an accessible language such as JavaScript has a solid complement of features to accommodate the kinds of arithmetic, trigonometric, and other operations typically supported by a programming language. Date manipulationalso numerically intensive, as it turns outis well supported in JavaScript as well. This chapter includes recipes for both of these areas.
For most scripters, the interior details about how JavaScript treats numbers is of little importance. In fact, the more you know about programming languages and different types of numbers, the more you need to forget in order to use JavaScript numbers. Unlike other languages, JavaScript has only one kind of number data type. All integers and floating-point values are represented by the same data type in JavaScript: number.
Internally, a JavaScript number is an IEEE double-precision 64-bit value. JavaScript provides a usable range of number values from 2.2E-208 to 1.79E+308 (boundary values obtainable by the static Number object properties Number.MIN_VALUE and Number.MAX_VALUE, respectively). JavaScript treats numbers beyond these limits as infinity, represented by Number.NEGATIVE_INFINITY and Number.POSITIVE_INFINITY. It is unlikely that you will ever refer to these four properties in your scripts, but the language has them for the sake of completeness.
Number values do not carry any formatting with them. If a value needs places to the right of the decimal to signify a fractional part of an integer, those places are there. But if a variable that once held a number with 10 digits to the right of the decimal is modified through an arithmetic operation to become an integer, the decimal and zeros to the right of the decimal disappear.
As with JavaScript strings (see Chapter 1), numbers are most commonly values (of data type number), but may also be created as more formal objects through the Number object constructor. Therefore, both of the following statements produce a piece of data that evaluate to the same numbers:
var myNum = 55; var myNum = new Number(55);
But if you examine the data types of the two objects (via the typeof operator), the first is number and the second is object. A number value inherits the properties and methods of the Number object, many of which are discussed in this chapter.
Available in every JavaScript context is a static Math object that provides a standard set of math constants and methods for working with numbers and trigonometry. At no time do your scripts create an instance of the Math object. It is simply "there" as a resource for your scripts to use as needed.
Table 2-1 shows the properties of the Math object. All of them are well-known constants in math circles. You can use these constants within JavaScript expressions. For example, to calculate the circumference of a circle ( times the diameter) whose diameter measure is in a variable d, the statement is:
var circumference = d * Math.PI;
Property |
Description |
---|---|
E |
Euler's constant (2.718281828459045) |
LN2 |
Natural logarithm of 2 (0.6931471805599453) |
LN10 |
Natural logarithm of 10 (2.302585092994046) |
LOG2E |
Log base-2 of Euler's constant (1.4426950408889634) |
LOG10E |
Log base-10 of Euler's constant (0.4342944819032518) |
PI |
(3.141592653589793) |
SQRT1_2 |
Square root of 1/2 (0.7071067811865476) |
SQRT2 |
Square root of 2 (1.4142135623730951) |
The long list of Math object methods is located in Table 2-2. Many of them support trigonometric operations, some of which can come into play for path animation with positioned elements. Others provide math services that are useful from time to time, such as taking a number to a power, rounding, and getting the minimum or maximum of a pair of number values. As with most JavaScript methods, the values passed as arguments to the methods are not altered in any way. Capture the results in a variable.
Method |
Description |
---|---|
abs(number) |
Returns the absolute value of number |
acos(number) |
Returns the arc cosine (in radians) of number (also in radians) |
asin(number) |
Returns the arc sine (in radians) of number (also in radians) |
atan(number) |
Returns the arc tangent (in radians) of number (also in radians) |
atan2(y, x) |
Returns the arc tangent (in radians) of the quotient y/x |
ceil(number) |
Returns the next higher integer that is greater than or equal to number |
cos(number) |
Returns the cosine (in radians) of number (also in radians) |
exp(number) |
Returns Euler's constant raised to the number power |
floor(number) |
Returns the next lower integer that is less than or equal to number |
log(number) |
Returns the natural logarithm (base e) of number |
max(number1, number2) |
Returns the greater value of number1 or number2 |
min(number1, number2) |
Returns the lesser value of number1 or number2 |
pow(number1, number2) |
Returns the value of number1 raised to the number2 power |
random( ) |
Returns a pseudorandom number between 0 and 1 |
round(number) |
Returns an integer of number+1 if number is greater than or equal to number + 0.5; otherwise, returns integer of number |
sin(number) |
Returns the sine (in radians) of number (also in radians) |
sqrt(number) |
Returns the square root of number |
tan(number) |
Returns the tangent (in radians) of number (also in radians) |
Since the very beginning of the JavaScript language, one of its most powerful objects has been the Date object. It is a global object in that every window (or frame) has a static Date object sitting in the background, ready to be invoked at any time. With only a couple of exceptions, the way you work with dates is to create an instance of the Date object via the constructor function for this object:
var myDate = new Date( );
Creating an instance of the Date object (which I call a date objectwith a lowercase "d") is like taking a snapshot of an instant in time. A date object contains information about the date and time, down to the millisecond, but it is not a ticking clock. Even so, you can use the myriad functions associated with every date object to read individual components of the date and time (year, month, day, hour, and so on). A parallel set of methods let you set the date and/or time of that date object instance. That's one way you can perform some date or time arithmetic, as shown in Recipe 2.10 and Recipe 2.11.
Be aware that the date object operates solely on the client computer in which the page is loaded. There is no connection with the server clock or its timekeeping abilities. This means that your date and time calculations are entirely at the mercy of the accuracy (and proper setting) of the client computer's internal clock. Not only must the date and time be reasonably accurate, but the time zone setting is critical. If the user is located in California, but the computer's time zone settings are for New York, the computer will be thinking strictly in New York time. This could disturb some date and time calculations, as shown in Recipe 15.8.^{[1]}
^{[1]} Internet Explorer 5 for the Macintosh introduces an extra wrinkle: it reads the system clock only at launch time and doesn't synchronize after that. If the computer goes to sleep, IE stops its internal clock and resumes at that point when the compute awakens. Let's hope no future browser makes that ghastly mistake.
If a script is concerned with the "ticking clock," the script must periodically create a new date object instance to get the latest snapshot of the clockand then perhaps compare it against some known deadline. Again, the discussion in Recipe 15.8 shows how to do this.
Working with dates in JavaScript can be rather puzzling at times. The most difficult concept to comprehend is when you create a date object (either for the present or some other date and time), the object instance stores its value as an integer representing the number of milliseconds from the start of January 1, 1970. More importantly, the point of reference for all date values is Coordinated Universal Time (UTC), which is essentially the same as Greenwich Mean Time (GMT). What makes this hard to understand is that when you create a date object instance and ask to view its value, the JavaScript interpreter automatically returns the computer's local date and time for that object, even though the GMT value is stored. For example, if you create a date object on a computer running in New York City at 10:00 P.M. Friday night, the date object preserves that date and time in GMT, or (during standard time months) five hours later than the time in New York (3:00 A.M. on Saturday). But if you ask to view the value of the date object (say, in an alert dialog box), the value reports itself to be 10:00 P.M. on Friday.
For the most part, this discrepancy between a date object's internal calculation and external display is of no consequence. Since all of your date objects behave the same way, calculations such as the amount of time separating two date objects yield the same results. You need to worry about this GMT offset business only when your calculations involve times in two different time zones. See Recipe 15.8 for an example of how to account for time zone offsets.
Look to recipes in this chapter for examples of how to perform date calculations; Chapter 15's recipes for additional practical applications in dynamic pages. The Date object is a powerful beast that, once tamed, can enliven the personalization features and dynamic aspects of your pages.