Make It Easy on Yourself

One of the things that makes JavaScript such a powerful, easy-to-use
language (compared to procedural C, say, which shares many of the same
syntactical constructs) is its relaxed data-typing: that is, its ability
to let you use strings and numbers more-or-less interchangeably, without
any need to perform explicit typecasts or adhere to type rules. In
JavaScript, a number is a number in numeric contexts and a string in string
contexts. That is, you can do things like:



var n = new String('30'); // create string, '30'

n = n * 2; // 'n' is now 60

n += '3'; // 'n' is now 603

n = n.substr(0,2); // 'n' is now 60 again

All of this, without generating an error. In any other language, the
Type Police would have you in jail in a nanosecond!

But relaxed typing is a double-edged sword. Sometimes, you NEED a number
to be a number, not a string. For example, suppose you have a function
called Sum(), which sums two values:


function Sum(n,m) {
return n + m;
}

Unfortunately, the function doesn’t ‘know’ whether the arguments being
passed are numeric, or strings. If either one is a
string, the return value will be a string! Thus, if ‘n’ equals the number 50,
but ‘m’ equals the string ‘2’, the value returned by Sum() will be the
string ‘502’, which may or may not be what you expected.

There are several ways of dealing with this. A not-very-elegant way
would be to check the types of the incoming parameters with JavaScript’s
typeof() function, which will return ‘string’ for a String object or ‘number’ for
a number, and perform any necessary conversions of non-numeric arguments.
A more sensible way to proceed is just to force the conversion to a number
by multiplying each argument value by one:


function Sum(n,m) {
return (1*n + 1*m);
}

Multiplying a string by one (or adding zero to it) is a very old
JavaScript hacker’s trick for performing explicit type conversion. Multiplying a
string by unity or adding zero to it puts the string in a numeric
context, which puts the JavaScript runtime interpreter on notice that the
expression in question needs to evaluate to a numeric result. The only downside to
this sort of approach is poor readability. Multiplying variables by unity
looks strange and ‘junks up’ your code to a certain extent. A more
readble approach is shown below:


function Sum(n,m) {
return (Number(n) + Number(m));
}

You can also use String() to convert numbers to strings, in place. If
the Number() and String() methods seem strangely familiar (yet odd in this
context), recall that core JavaScript provides for the use of
constructor functions by these names. To construct a string or
number, you can do:


var s = new String('Hello World!');

var n = new Number(9);

The same methods, minus the ‘new’ keyword, can be used to force an
explicit ‘typecast’ on the fly. I’ve found that this can be incredibly handy when
you’ve got a situation in which you can’t remember whether you’re
dealing with a number or a string (but you know you need one or the other). A
good rule of thumb is this: When you KNOW you need a number, explicitly
coerce every value to a numeric value. Otherwise, the day will come when you
(or your user) will see the famous NaN (Not-a-Number) error in the
JavaScript console at runtime, indicating that your code tried to use a string as a
number, and failed. (It happens!)

Another Way to Make Strings

Don’t forget that on those occasions when you want to be certain that
you’re dealing with a string, you can force ANY JavaScript data type or
object to become a string by applying the toString() method, which is
available at all times to all data types and objects. (You can even
apply this method to functions. Try it!)

Of course, once you’ve made something into a string, either with the
ubiquitous toString() method or some other way, you then have all the
power and utility of the String class methods available to you. This means,
for example, that you can truncate decimal numbers to a given number of
digits quite easily:


var pi = Math.PI; // pi is now 3.14159265358979

pi = pi.toString().substr(0,7); // now it's 3.14159
pi = pi.toString().substr(0,4); // now 3.14

The substr() method takes a starting offset and a length value. It
extracts a substring from the parent object, starting at the offset given and
continuing for ‘length’ characters.

Dates as Numbers

The Date object is a good example of how JavaScript entities can take on
numeric attributes or string attributes depending on the context and
circumstance. Try this exercise: Create a button using Acrobat’s form
tool and link this line of JavaScript to the mouse-up event:


app.alert(new Date);

When you click the button (causing the script to fire), you will see an
alert dialog bearing a message similar to:


Tue Feb 22 13:15:08 2000

Obviously, in this context, a Date object is being treated as a string.
But if you multiply the Date object by 1.0, shown below, you get a much
different result:


app.alert(new Date * 1.0); // alert says: 951243107745

(Note that parens are optional on Date.)

The long number shown in numeric context is the Date’s raw value: the
number of milliseconds since January 1, 1970. (Just multiplying it by
one coerces it to a numeric value.) This can obviously be handy if you need
to set a ‘time out’ value in a script. Suppose that you want to set a form
up so that after a certain date (say July 4, 2000), a given field displays
with a background color of red.


var deadline = new Date('Jul 4 2000');

if (new Date() - deadline > 0)
this.getField('fieldname').bgColor = ['RGB',1,0,0];

The numeric context in the condition check forces the dates to become
numbers: raw millisecond values. Since a future date is a bigger value
than a more recent date, the subtraction produces a negative number until the
deadline passes. After the deadline has passed, the difference is
positive.

Dates As Strings

But once you understand that an object can be both a number and string
(depending on context), it’s easy to deal with dates as strings. For
example, if you want to show the current date in a form field called
‘current_date’, but you don’t want to display the day of the week nor
the hours:min:sec information returned in a call to new Date(), use the
string method, substr(), to extract just the info you want to display:


var date = new Date();

this.getField('current_date').value =
date.toString().substr(4,7)+
date.toString().substr(21,4);

The display will be something like: ‘Feb 29 2000’.

Characters as Numbers (and Vice Versa)

Finally, let’s consider how to convert a character (a letter) to an
ASCII value (a number), or vice versa.

To get the numerical (ASCII) value of a character code in JavaScript,
you have to use the charCodeAt() method of the String class.


var asciiValue = 'e'.charCodeAt(0); // asciiValue is 101

Notice here, I resort to the useful trick of applying string methods to
a single character treated as a string literal. (Anything between
quotation marks qualifies as a string object.) To get a character value from a raw
number, you use the static String method, fromCharCode():


var str = new String; // create empty string

str += String.fromCharCode(101); // add 'e'

Since fromCharCode() is a static method, you call it using the class
name (‘String’) as the parent object.

One caveat applies here. In Acrobat 4.xx (on my Mac, at least), the
charCodeAt() method returns a negative number for ASCII values greater
than 127. This is contrary to the behavior of core JavaScript in other
environments (such as in Netscape browsers), where charCodeAt() returns
only positive numbers. I’m told this ‘feature’ may be corrected in the
next release of Acrobat, which will use the JavaScript 1.4 engine. Until
then, remember to watch out for ‘negative ASCII values’ when using
charCodeAt() in Acrobat.

You May Also Like

About the Author: Kas Thomas

Leave a Reply