One of the delights of spending a few minutes every day playing with JavaScript is that you regularly learn new things about
the language. Occasionally you stumble upon some real shockers. These provide the classic ‘Aha!’ moments that take your
programming skill to the next level.
Some of my best ‘Aha!’ moments of the past six months are captured in the quiz below. If you’re a serious user of JavaScript,
I strongly urge you to take this quiz, because odds are, you’ll learn a lot. Note that this particular quiz covers only
standard JavaScript core-language functionality, not anything Acrobat-specific. In other words, the answers to these
questions will apply to all JavaScript environments (not just Acrobat). In my next column [next week], we’ll look at a quiz
that targets Acrobat-specific knowledge.
It should take you no more than 10 minutes to finish this quiz. The test consists of twenty simple JavaScript expressions,
each of which can be evaluated by the runtime interpreter exactly as shown. In other words, you could cut and paste any of
the following expressions directly into the Acrobat script console, then hit Enter on the numeric keypad and see the answer
appear. What I’m asking you to do is guess what the console would show if you were to evaluate each expression below.
Answers (and discussion) follow:
To what value will each of the following expressions evaluate in the JavaScript console?
- ‘6’ + ‘5’ * 2
- typeof null
- null == undefined
- typeof typeof null
- typeof NaN
- 5 + true
- typeof /abc/
- a = 4; b = 6; a+++b;
- 011 * 2
- (function a(n) { return 123; })( )
- ‘abc'[2]
- (16).toString(16)
- ‘u0061’
- NaN == NaN
- [1024,25,3].sort()
- ‘B’.bold()
- ++Math.PI
- Boolean(‘abc’ < 'XYZ')
- typeof Infinity
- typeof 1/0
ANSWERS:
- ‘610.’ The interpreter, when encountering mixed data types
in an expression, casts strings to numbers for purposes of
multiplication, but casts numbers to strings for purposes of
addition. (That is, the plus sign is always treated as a
string-catenation operator, unless every ‘summand’ is of type
number.) Since ‘5’ * 2 is a numeric operation
(multiplication), ‘5’ is cast from string to number, giving
the result 10. But since ‘6’ is a string, ‘6’ + 10 means 10 is
cast to a string. Hence the resulting string ‘610.’ - Null, interestingly, has a type: object. Nevertheless, it
has no properties. Null is simply a placeholder value that,
while not designed to be operated on directly, can be assigned
to a variable so that the variable can operated on without
causing an exception. - true. An untyped comparison of null and the special value
undefined (without quotes) shows that they evaluate to the
same value. A typed comparison (using ===) of the two gives
false, because null is of type ‘object’ (see preceding
question) while undefined is of type ‘undefined.’ - ‘string‘, because typeof always returns a string.
- ‘number‘, oddly enough. NaN is a special value in
JavaScript. It means ‘not a number.’ You will encounter NaN at
runtime when you try to do something like multiply your
mother’s maiden name by the square root of two. - 6, because the interpreter casts true to the number one in
this context. - ‘function‘, strangely enough. One would expect regular
expressions to be of type object, since they have methods and
properties. Nevertheless, you can’t invoke a regular
expression as a function. If you try executing /abc/(), you
will crash Acrobat. - JavaScript evaluates left-to-right, so the answer here is
10. The construction a+++b means ‘add a to b and
post-increment a’ (i.e., a++ + b). It doesn’t mean to
pre-increment b and add a to it, which would of course give a
different result. - 18 (because 011 is octal for 9).
- 123. Putting a function declaration between parentheses
and then following it with () is the same as calling the
function anonymously. - c. You can use array indexing on strings. There is never
any need to use charAt(). - 10. When a number argument is supplied to toString(), it
is treated as a radix or number-system base. Hence, you can
use toString() to convert integers to their hex, octal,
binary, base-9, etc. representations. The base-16
representation of 16 is, of course, 10. - ‘a‘. The backslash-u notation means you are specifying a
two-byte Unicode value in hex. ASCII 97 (hex 61) is the
lowercase letter ‘a’. - false. If you are familiar with the ECMA-262 specification
(JavaScript standard) you’ll recall that any comparison
involving NaN gives false. This even applies when NaN is
compared to itself! To compare something to NaN, use the
built-in method isNaN(). - [ 1024,25,3 ] The numbers don’t change order, because
sort(), by default, casts array members to strings before
comparing them. Therefore the answer is just an alphabetized
version of the input. To sort an array of numbers numerically,
you need to supply your own custom comparator function:[1024,25,3].sort(function(a,b){return a>b}) // gives 3, 25, 1024
- B. This seems utterly incredible at first, not only
because we’ve all been told that Acrobat JavaScript knows
nothing about the HTML world (which is true), but also because
String methods like big(), bold(), link(), blink(), etc. are
nowhere defined in ECMA262-3. It appears these methods, which
‘wrapper’ strings in HTML tags, are a Netscape legacy that
found their way into Acrobat. It’s mostly useless for Acrobat
programmers, but an interesting bit of functionality
nonetheless. - 4.141592653589793. Yes, you can preincrement Math.PI.
- false. String comparisons of this sort proceed bytewise
using ASCII numeric values, and lowercase letters have greater
numeric values than their uppercase equivalents. - number
- NaN. The value of 1/0 is Infinity (a number), yet its type is not a number. Go figure.
This is an extremely challenging quiz, so if you got more than
half the questions right, you are fully justified in
considering yourself a JavaScript expert, and I lay my
unworthy hat at your feet. If you’re only an occasional user
of JavaScript, I would not expect you to get more than two or
three questions right. Don’t feel bad if you said ‘Huh?’ to
every single question.
Next time, we’ll look at a more realistic set of problems
involving Acrobat’s own JavaScript extensions. Until then, may
your code be unexceptional (that is, not throw exceptions) and
may your next airline ticket say ‘JFK’!