Chapter 36
Debugging Scripts
Development environments usually include at least one powerful debugger, and sometimes
a multitude of them. In fact, experienced programmers, when introduced to a new language,
are concerned first and foremost about the power and the productivity factor of the
debugger. The debugger is the most powerful tool an advanced computer scientist uses to
find his or her bugs, and we have yet to meet a programmer who does not have bugs in his
or her code. Sources for bugs range from simple ones like typos to logic problems in very
complex applications like the Tetris game.
JavaScript is not in the same league as other development environments in providing a
debugger for its developers. The smartest JavaScript editor to date is Infuse by Acadia
(see www.acadians.com). This environment provides you with all language features
online, and thus can help you write a better code with less bugs. But, at the end, you
still end up with a script that can have bugs and there is no debugger to find it with.
You have to revert to the old way people used to debug their programs: printing messages
and progressive commenting of lines.
Types of Errors
In a traditional language, such as C, there are two main types of errors: compiletime
errors (syntax) and runtime errors. Since JavaScript is not a compiled language, the
boundaries between these two types of errors are blurred. As the page loads, the first
type of errors the browser is looking for are syntax ones. These are relatively
easy to detect and fix. Misspelling else in the if-else construct is one
example of a syntax error. Runtime errors involve mismatching between function definitions
and function calls, undeclared variables located on the right-hand side of assignment
operators, mismatches between object types, etc. If the script lines execute immediately
as the page loads, undeclared variables will be flagged immediately. Other errors will be
detected when culprit functions execute, which may occur upon loading or while responding
to user actions. In fact, some errors, if not invoked as a response to user actions, may
never be detected. This kind of issue belongs to a wider field of Coverage Analysis. There
are methodologies and tools for mainstream languages that measure the percentage of code
covered by a specific testing suite, where the coverage can be measured by the percentage
of lines or functions executed by the suite. Such a tool is yet to be developed for
JavaScript.
Error Messages
Navigator and Explorer behave very similarly when detecting a problem. They produce a
large alert box (Figure 36-1a and Figure 36-1b) specifying:
- The URL or filename of the document causing the problem
- The line number
- A description of the problem in a very condensed and terse statement
- An extract of the code that JavaScript could not handle
- An arrow marker pointing to the offending word
The line number shown in the alert box is exactly the line count of the code extract
shown in the alert box, where the first line of the file is at count one. Some authors
mistakenly write that the line number is counted from the opening <script>
tag of the group that contains the code extract.
Figure
36-1a: A typical Navigator error message window.
Figure
36-1b: A typical Internet Explorer error message window.
Debugging JavaScript may be tricky at times. You have to infer from the shown code
extract what might be the real problem. In Figures 36-1a and 1b, for example, the problem
is a missing closing brace for the function defined before the shown getAmpm()
function. Some error messages, as Figure 36-2 shows, do not provide the code extract but
rather the offending element (a property name for example) instead.
Figure
36-2: The property “abcd” is provided instead of the code
extract.
The number of error message types is large and we do not list all of them here. The
rest of this chapter provides the most important ones with some explanations on proper
remedies to the problems.
"string is not
defined"
This error usually points to an uninitialized variable being referenced to another
variable (two-operands statement) or to itself (unary-operand statement). Obviously, this
variable has not been declared or assigned a value prior to the line provided in the error
message window. There may be several reasons for this bug:
- The variable string has been initialized as a local variable in another function.
Search for string in your file and check if this is the case.
- You have intended to enclose string in quotes but forgot. Check if this is the
case.
- You have misspelled a variable that has been declared before. Check if you have a
similar name for a variable that has been initialized before the culprit statement. Also,
since JavaScript is case sensitive, see if the variable name is different from previously
defined variable names by the case of one or more of its characters. Use the
case-insensitive option of your editor to search such matches.
- If the erroneous statement starts with a function, you either have a bug in the script
above the flagged line (failed to balance braces for example) or are calling a function
that is defined in another window or frame, but you forgot to include the reference to
that window or frame.
"string is not a
function"
The following problems are the most common sources for such a bug:
- There is a mismatched case of letters between the calling statement and function
definition.
- You are reusing a variable or HTML object name by the function name. Use your editor to
search for string.
- There is a problem in the script above the function named in the error message window.
Do some detective work.
"unterminated string
literal"
This error message will usually point to the first quote of a string it thinks is not
terminated. This is a very common error when trying to concatenate strings or nest them.
You can avoid nesting strings by using a pair of \” in-line quote symbols or using a
variable to indirectly reference a string.
"missing } after
function body"
A brace is missing somewhere in the function, not necessarily where the error message
says. When a function includes several nested items such as if..else or for
loop constructs, it is not so obvious where the brace is missing. An intelligent editor
can be of help here to match braces, pair by pair.