Three common mistakes in JavaScript / EcmaScript
Here are three common mistakes I've seen recently in script files.
- Undefined is not null, except that it is.
If you've been writing code in a strongly-typed language recently, you're used to checking the nullity of objects before you use them, like this:
if (SomeObject.foo !== null) {
Well, in JavaScript, something that has not been assigned to is not null, it's undefined. Undefined is different from null when using !== but not when using the weaker != because JavaScript does some implicit casting in this case. Well, anyways, you can use typeof to explicitly check for undefined, or use the weaker equality operators, but the shortest way to deal with this, and also the one that best expresses your intention of checking if an object is safe to use is probably to just rely on the type-sloppiness of JavaScript and count on it to evaluate null and undefined as false in a boolean expression, like this:
if (SomeObject.foo) {
It's very important to keep the undefined case in mind. Another case is when you expect a function to return a boolean value. What if the function forgets to return a value in some cases? Well, its return value is then undefined, which is false. So if your own default value should be true, you should really write this:
if (SomeFunction() !== false) {
Which is different from if (SomeFunction()). By the way, note the strict equality here, which preserves you from strange things like "" == 0).
But let me summarize and potentially add to the confusion before we move on to the next trick:
undefined false (SomeObject.foo) false false (SomeObject.foo != null) false true (SomeObject.foo !== null) true true (SomeObject.foo != false) true false (SomeObject.foo !== false) true false - You can't overload a function.
Developers who are used to languages like Java and C# overload methods all the time. Well, in JavaScript, there are no overloads, and if you try to define one, you won't even get an error. The interpreter will just pick the latest-defined version of the function and call it. The earlier versions will just be ignored.
The way you simulate overloading is twofold. First, if a parameter is omitted, it is undefined. And second, there is a special variable, arguments, which is an array of the function parameters. Based on the type of each parameter, you can do different things. But it's kind of ugly.
- Undeclared variables are global.
Always, always declare your variables using the var keyword. If you don't, your variable is global. So anyone who makes the same mistake as you (or more likely, if you do the same mistake in two different places) will create nice conflicts which give rise to very difficult-to-track bugs. Even loop counters should be properly declared.
There is actually a good way to do some basic sanity checks on your script files (like multiple declarations, forgotten declarations, unassigned variables, etc.): in Firefox, go to the about:config url and look for the javascript.options.strict entry. Set it to true. Now, you can point the browser to your JavaScript file. You'll get a lot of new warnings that will point to the problems in your code (if any, but I doubt that you'll get zero warnings the first time you do that).
UPDATE: removed the useless rant at the beginning (I now quite like JavaScript) and corrected some mistakes in #1.