It's time to do a rundown of seven common mistakes. Some of these you'll learn to avoid as you become more experienced, but others may haunt you forever!
JavaScript is actually very easygoing when it comes to defining your variables before assigning values to them. For example, the following will implicitly create a new variable abc and assign it to the value 23.
abc = 23;
Although strictly speaking, we should define the variable explicitly.
var abc = 23;
(Actually, whether you use the var keyword has a consequence on the scope that the variable has, so in fact it is always best to use the var keyword.)
However, if a variable is actually used before it has been defined, an error will arise. For example, the following code will cause the error shown in Figure 10-1 if the variable abc has not been previously defined (explicitly or implicitly).
alert(abc);
In addition, we must remember that function definitions also have parameters, which if not declared correctly can lead to the same type of error.
Take a look at the following code:
function resetQuiz(numberOfQustions, timeLimit) { timeLeft = timeLimit; totalQuestionsToAsk = numberOfQuestions; currentQNumber = -1; questionsAsked = new Array(); numberOfQuestionsAsked = 0; numberOfQuestionsCorrect = 0; }
If we call this function, we get an error message similar to the one shown in Figure 10-2.
The error here is actually a simple typo in the function definition. The first parameter has the typo: It should read numberOfQuestions not numberOfQustions. What can be confusing with this type of error is that although the browser tells us the error is on one line, in fact the source of the error is on some other line.
This is a major source of errors, particularly because it can be difficult to spot at times.
For example, spot the three case errors in the following code:
var myName = "Paul"; If (myName == "paul") alert(myName.toUppercase());
The first error is that we have typed If rather than if. However, JavaScript won't tell us that the error is an incorrect use of case, but instead IE will tell us "Object expected" and Netscape will tell us that "If is not defined." Although error messages give us some idea of what's gone wrong, they often do so in an oblique way. In this case IE thinks we are trying to use an object called an If object and Netscape thinks we are trying to use an undefined variable called If.
Okay, with that error cleared, we come to the next error, not one of JavaScript syntax, but a logic error. Remember that Paul does not equal paul in JavaScript, so myName == "paul" is false, even though it's quite likely that we didn't care whether it was paul or Paul. This type of error will result in no error message at all, just the code not executing as we'd planned.
The third fault is with the toUpperCase() method of the String object contained in myName. We've written toUppercase, with the C in lowercase. IE will give us the message, "Object doesn't support this property or method" and Netscape will report that, "myName.toUppercase is not a function." On first glance it would be easy to miss such a small mistake and start checking our JavaScript reference guide for that method. We might wonder why it's there, but our code is not working. Again we always need to be aware of case, something that even experts get wrong from time to time.
In the following code we define a function and then call it. However, there's a deliberate mistake. See if you can spot where it is.
function myFunction() { x = 1; y = 2; if (x <= y) { if (x == y) { alert("x equals y"); } } myFunction();
If we properly format the code it makes it much easier to spot where the error is.
function myFunction() { x = 1; y = 2; if (x <= y) { if (x == y) { alert("x equals y"); } } myFunction();
Now we can see that we've forgotten to mark the end of the function with a closing curly brace. When there are a lot of if, for, or do while statements, it's easy to have too many or too few closing braces. With proper formatting, this problem is much easier to spot.
In the following code, there's a deliberate concatenation mistake.
var myName = "Paul"; var myString = "Hello"; var myOtherString = "World"; myString = myName + " said " + myString + " " myOtherString; alert(myString);
There should be a + operator between " " and myOtherString in the fourth line of code.
Although easy to spot in just a few lines of code, this kind of mistake can be harder to spot in large chunks of code. Also the error message that a mistake like this causes can be misleading. Load this code into a browser and we'll be told "Error : Expected" by IE and "Missing ; before statement" by Netscape. It's surprising how often this error crops up.
Take a look at the following code:
var myNumber = 99; if (myNumber = 101) { alert("myNumber is 101"); } else { alert("myNumber is " + myNumber); }
We'd expect, at first glance, that the alert() method in the else part of the if statement would execute telling us that the number in myNumber is 99, but it won't. We've made the classic one equals sign instead of two equals signs mistake. Hence, instead of comparing myNumber with 101, we have set myNumber to equal 101. If, like me, you program in languages, such as Visual Basic, that use only one equals sign for both comparison and assignment, you'll find that every so often this mistake crops up. It's just so easy to make.
What makes it even trickier is that no error message will be raised; it is just our data and logic that will suffer. Assigning a variable a value in an if statement may be perverse, but it's perfectly legal so there will be no complaints from JavaScript. When embedded in a large chunk of code, a mistake like this is easily overlooked. Just remember next time your program's logic seems crazy, that it's worth checking for this error.
One piece of good news is that NN 6 and 7 will issue a warning when we make this mistake along the lines of: "test for equality (==) mistyped as assignment (=)?".
Note that it's only a warning and not an error, so no error messages will appear. The difference between warnings and errors is that a warning is issued for code that is syntactically correct, but that does appear to be flawed logically. Errors are where the syntax of the code is invalid. We'll see later how we can use the Netscape JavaScript console to view errors and warnings.
Take a look at the following code:
if (myVariable + 12) / myOtherVariable < myString.length)
Spot the mistake?
The problem is we've missed a parenthesis at the beginning. We want myVariable + 12 to be calculated before the division by myOtherVariable is calculated, so quite rightly we know we need to put it in parentheses.
(myVariable + 12) / myOtherVariable
However, the if statement's condition must also be in parentheses. Not only is the initial parenthesis missing, but also we have one more closing parenthesis than we have opening parentheses; the numbers must match. For each parenthesis opened, there must be a corresponding closing parenthesis. Our code should be as follows:
if ((myVariable + 12) / myOtherVariable < myString.length)
When we have lots of opening and closing parentheses, it's very easy to miss one or have one too many.
Our final common error is where either we forget to put parentheses after a method with no parameters, or we use a property and do put parentheses after it.
When calling a method we must always have parentheses following its name; otherwise JavaScript thinks that it must be a property. For example, examine the following code:
var nowDate = new Date; alert(nowDate.getMonth);
In the first line we have used the Date constructor, which is simply a method of the Date object, with no parentheses.
On the second line, we call the getMonth() method of the Date object, except that we've forgotten the parentheses here also.
This is how lines should be:
var nowDate = new Date(); alert(nowDate.getMonth());
Just as we should always have parentheses after a method, we should never have parentheses after a property, otherwise JavaScript thinks we are trying to use a method of that object:
var myString = new String("Hello"); alert(myString.length());
In the second line we have used parentheses after the length property, making JavaScript think it is a method. We should have written it like this:
var myString = new String("Hello"); alert(myString.length);
This mistake may seem like an obvious one in two lines of code, but it's easy to slip up when we're pounding out lots and lots of code.
Now that we've seen these top seven mistakes, we'll take a look at one way to make remedying these errors easier. This is through the Microsoft script debugger.