Although not authored by us, here is a quick reference guide that helps you find errors, even without the aid of a debugging utility. We encourage you to take the time to look over this quite thorough debugging column and chances are you will fix your scripts!
Everyone makes mistakes writing JavaScript programs. Errors don't know experts from novices, so the next time you get an error message while trying to play a JavaScript program you've written, don't feel bad. JavaScript provides error messages as a means to help you spot mistakes. This column describes the errors you are likely to get when writing a JavaScript program and what to do about them.
They say that novels are not written, but rewritten. Certainly the same goes for computer programs, including those written in JavaScript. Bugs are the bane of any programmer, and debugging is part of the program development process.
Unfortunately, client-side JavaScript currently lacks a debugging utility, so finding errors in your script becomes a lesson in deductive reasoning. You cannot -- as yet, anyway -- set a breakpoint and have Netscape display the contents of registers or variables if a program terminates unexpectedly.
Debugging a JavaScript program entails using problem-solving techniques that would impress Sherlock Holmes. Effective debugging of JavaScript requires some experience writing programs for it. After a while, you become familiar with the error messages JavaScript displays and learn ways to solve the errors. Of course, you may not have the time to devote yourself to learning all the intricacies of JavaScript. This column is your quick-reference guide to understanding how to effectively debug JavaScript programs, even without a debugging utility.
Determining the type of error There are three general types of errors that can occur when playing a JavaScript program. These errors are:
Load-time errors are perhaps the most common and are generally caused by problems in syntax. To help you determine the problem, JavaScript displays a warning box when a load-time error occurs. The warning box tells you the problem and, most of the time, shows you the actual text of the error. Bear in mind that the warning box doesn't always indicate the actual error. Depending on the problem, the error may be located at a different part of the line or even on another line.
As an example, general errors in syntax, such as forgetting to provide the proper open and close braces around a function, create a load-time error. Here's one such example (the actual error message is "missing } after function body"):
function test () { alert ("hello")
Where load-time errors are generally caused by mistakes in syntax, runtime errors are most often due to improper use of commands. For instance, you will receive a runtime error if you reference a variable that hasn't been defined. The following results in a runtime error.
Messsage = "This is a test"; // note three s's document.write(Message); // note two s's
Another type of runtime error occurs when you misapply one of JavaScript's objects. For example, this code fragment results in an error ("document cannot be set by assignment.") because you cannot assign a value directly to the document object.
document="test";
Common causes of errors You'll find that most of the errors that beset your scripts are caused by the same, and rather simple, mistakes. Make sure you look for the following:
MyVar
MyVal
Name
Names
for
Determining the source of a problem An important step in repairing a broken script is isolating its various functions and routines, and analyzing it on a piece-by-piece basis. This can be done using a number of low-tech approaches, such as setting watchpoints using alert message boxes, and taking advantage of the for/in statement to peer into JavaScript's objects.
Setting watchpoints Many logic errors are caused by incorrect values in variables. One way to help you spot these logic errors is to set "watchpoints" at one or more spots in the script. These watchpoints are alert boxes that display the contents of the variables. You can also use alert boxes to determine if your code is reaching a certain point in the program. (I use something like alert("to here") to verify the code is working.) Remove the alert watchpoints after the script has been debugged.
Type single-line command entry in the Location box A little-known JavaScript testing shortcut is to type a JavaScript command line in Netscape's Location box. Preface the command line with the JavaScript: protocol, like that shown below, and press the Enter key to see the result:
JavaScript:
javascript:alert ("this is a test")
javascript:document.write ("this is a test")
true
If you need to test a number of command lines, you can reduce the keystrokes by typing javascript: (remember the colon) in the Location box. Netscape displays a "JavaScript typein" frame at the bottom of the window. Type the command line you want to try, and press Enter.
javascript:
Type multiple-line commands using a helper script The "JavaScript typein" frame window described above is defined within Netscape. You can create your own version of it to allow for simplistic multiple-line command entry (this script is very basic and can be improved, but it serves to get you going). The following displays a multiline JavaScript typein utility. The multiline command entry script is a combination frameset and JavaScript-generated frame document. To use, type the script segment you want to test in the text-area box, and choose Run.
Note: When using this script be sure to append semi-colons (;) at the end of each line. This helps JavaScript properly parse the command lines you enter.
<SCRIPT> function jsinput () { parent.MochaInput.document.write ("<b>JavaScript input</b>") parent.MochaInput.document.write ("<form action=JavaScript: target=MochaOutput>") parent.MochaInput.document.write ("<textarea name='isindex' rows=5 cols=50>") parent.MochaInput.document.write ("</textarea><BR>") parent.MochaInput.document.write ("<input type='submit' value='Run'>") parent.MochaInput.document.write ("</form>") } </SCRIPT> <FRAMESET ROWS="50%%,50%%"> <FRAME NAME="MochaOutput" SRC="about:blank"> <FRAME NAME="MochaInput" SRC="javascript:parent.jsinput()"> </FRAMESET>
Make paper copies JavaScript programs are composed of text embedded in HTML documents. Therefore, you can use any text editor program that has a print capability to make paper copies of your scripts. The paper copies may help you find errors that are otherwise hidden in screenfuls of code displayed on your monitor.
You may find it helpful to print your JavaScript programs in a monospaced font, such as Courier, to help spot such mistakes as a string that is empty but should contain a space. The monospace font is better suited to locating these kinds of errors, but it does takes up more space on the line. Use a small 9- or 10-point font to compensate.
Use a simple object inspector The for/in statement can be used to create a simple object inspector. The following short script is all you need to inspect a JavaScript object. For example, to get a listing of the current properties of the window object, load the script and type window in the prompt box. Choose OK. JavaScript displays an alert box listing each property of the window object.
window
Important note: Do not use this script with Netscape 2.0 running under Windows 3.1 (other operating systems and later versions are fine). The script uses the eval function, which is known to cause a GPF when running in Netscape 2.0 under Windows 3.1.
eval
<SCRIPT> ret = prompt ("Enter object", "document"); obj = eval(ret); var temp = ""; for (x in obj) temp += x + ": " + obj[x] + "\n"; alert (temp); </SCRIPT>
Six mistakes everyone makes Here are a half-dozen of the most common mistakes people make when writing JavaScript programs. These are listed in no particular order.
1. Missing quotation marks for strings This should go without saying, but I'll say it anyway: Remember to provide quotes (either single or double) for all strings. The obvious use -- and most common site of abuse -- is the document.write method.
document.write(<H1>This is a heading</H1>);
2. Mismatching quotation marks JavaScript lets you use the single quote (') or the double-quote (") to delineate strings. However, you must be careful to stick with the same type, or else JavaScript will render an error message. The following is not allowed, because the characters used for the quote symbol are not consistent.
document.write("<H1>This is a heading</H1>');
document.write('<H1>Ways to "Improve" Your JavaScript Programs</H1>');
3. Using single equals instead of double equals in comparison expressions This mistake is so common (unless you're a dyed-in-the-wool C programmer) you're bound to do it at least once. JavaScript expects to see two equals signs in a comparison expression, not one. This is a mistake:
if(MyVar = "xyz")
4. Referencing objects that don't yet exist Netscape processes a page in the order it receives its HTML markup. It is common to place JavaScript code at the beginning of the page (usually in the <HEAD> tag). This can lead to errors if you attempt to reference some other part of the page that hasn't been loaded. For example, the following JavaScript attempts to reference a form control when the page is loaded. This reference comes before the control has been defined, so an error occurs.
<SCRIPT> document.write ("Hello<P>"); document.test.box.value = "Hello again"; </SCRIPT> <FORM NAME="test"> <INPUT TYPE="text" NAME="box"> </FORM>
5. Using the wrong object hierarchy with forms A common problem is referring to a form as a property of a window. This results in a confusing error -- "formname has no properties" (formname is the name of the form). It's confusing because the form is obviously an object with properties. For example, the following JavaScript says "test has no properties," yet it's obvious the test form is a valid object with properties:
<FORM NAME="test"> <INPUT TYPE="text" NAME="box"> </FORM> <SCRIPT> window.test.box.value = "Hello"; </SCRIPT>
document.test.box.value = "Hello";
6. Using string methods with objects that don't support those methods Some of JavaScript's objects return values that look like strings, but they are not true strings. For instance, the following displays the name of the current document URL. Although the return value looks like a string, it is not, and therefore doesn't support any string object methods or properties, such as indexOf or toUpperCase.
indexOf
toUpperCase
var ret = location; alert (ret.toUpperCase()); // results in an error
toString
var ret = location.toString(); alert (ret.toUpperCase()); // no error this time
JavaScript error messages Here is a list of the more common error messages you are likely to encounter when working with JavaScript. The messages are listed in alphabetical order in two sections: load-time errors (errors that occur when a script is loaded into the browser) and runtime errors (errors that occur when you play a script).
Load-time error messages These error messages appear when an HTML document containing JavaScript is first loaded.
function does not always return a value JavaScript found one or more return statements in a function that returned a value, and at least one return statement that didn't return anything. For example, the following script will result in an error in JavaScript:
function myBadFunction (val) { if (val==0) return; else return ("some text") }
identifier is a reserved word You tried to name a variable or object with a word that is reserved by JavaScript. Some words are reserved because they are used by JavaScript as names for statements, functions, methods, or objects. Other words are reserved for future use. These words are not currently used by JavaScript, but may be used some day. For example, the word int is reserved for future use. Using int as the name of a variable results in the "identifier is a reserved word" error:
int
int = "this is a test";
missing ( ... missing ) ... These errors (the ... denotes additional error message text) occur when you've forgotten to add the appropriate opening or closing parenthesis in your JavaScript code. For example, the error "missing ) after for-loop control" occurs with the following:
for (Count=1; Count<100; Count++ {
missing ; after for-loop condition missing ; after for-loop initializer The for statement is missing one or more semicolons (;) to separate its arguments. This error typically occurs when you've used commas instead of semicolons -- a common mistake because JavaScript uses commas as an argument separator for everything but the for loop (the syntax of the JavaScript for loop comes from C). As an example, this results in an error:
for (Count, Count<10, Count++) {
missing { before function body missing } after function body missing } in compound statement These errors occur when you forget to add the requisite brace either for a function or part of a compound statement (with, if, for, for/in, while). For instance, in the following you need a } to close out the for loop.
with, if, for, for/in, while
for (Count=1; Count<10; Count++) { var varOne=1; var varTwo=2;
nested comment JavaScript doesn't like you to nest /* multi-line comments. The following results in an error. To fix the error remove the second /*.
/* this is a test /* of a nested comment*/
out of memory This error message says JavaScript is out of memory and cannot perform any more actions. It typically occurs in scripts that create lots of string objects. A common example is the scrolling "marquee" used to move a train of characters across the screen or status bar. The better-written marquees shouldn't exhibit short-term "out of memory" problems, but because of code-cleanup bugs in JavaScript, continued use of the script will eventually lead to a memory failure.
syntax error This is JavaScript's generic error message. It appears if JavaScript detects a syntax problem with the script but cannot determine precisely what it is, usually because the code leaves JavaScript in an unknown state. For example, an incomplete assignment such as the following triggers the "syntax error" message:
ThisResultsInAnError=;
test for equality (==) mistyped as assignment (=)? Assuming equality test JavaScript uses double equals signs when testing for equality, such as in an if or while expression. This error occurs if you use only one equals sign. Fix the problem by adding a second equals sign. Here is a before-and-after example:
if
while
if (color="blue") // not accepted if (color=="blue") // accepted
unterminated string literal This is a common problem, caused when you forget to append a " or ' character to end a string literal:
NameOfMyCat="Santana
MyString = "first part "; MyString += "second part "; MyString += "third part";
Runtime error messages In the following error messages, xyz denotes variable text that JavaScript provides, such as a function or variable name. These errors occur at runtime -- that is, after the script has been loaded and code is executed.
Note: The xyz identifier may not always appear in the error message. For example, instead of saying "myObject cannot be indexed as an array," the error message may simply say, "cannot be indexed as an array." Fortunately, JavaScript does provide the number of the approximate line that contains the error, which can help in tracking down the source of a problem.
xyz cannot be indexed as an array Only objects can be indexed as an array, and this error typically occurs when you attempt to use a non-object as an array (the error also occurs if you attempt to use an array not supported by a given object, such as document.elements[0]). The following results in an error because window.length is a property, and not an object.
alert (window.length[0]);
alert (document[0]);
xyz has no properties The object you've referenced has no properties. This is a common error, and is usually the result of misusing objects. This error will crop up, for example, with the following:
document.history.go(1);
window.history.go(1)
xyz is not defined This error occurs when your JavaScript code references a variable or object that does not exist. For example, you get the error with the following. (Note that the assigned variable is Test, whereas the variable used with the alert method is Text.)
var Test="This is a test; alert (Text);
var Test="This is a test; alert (test);
Conclusion Debugging JavaScript programs may not be state-of-the-art (yet, anyway). Nevertheless, with a bit of sleuthing, and a handful of simple tools and techniques, you can debug most any JavaScript coding problem you may encounter. And as you might expect, the process gets easier as you become more experienced at programming in JavaScript.
Additional Resources