There are plenty of posts discussing anti-patterns in other languages, like Java or Python. However, I haven’t really seen much regarding JavaScript besides this question on StackOverflow. And most of the ones I found don’t separate the DOM API and the JavaScript language itself.

So the following is a list of JavaScript anti-patterns that I’ve compiled, with some explanations.

Polluting the global namespace

This is the biggest no-no, and is something all new JavaScript developers must learn. The reason you don’t want to declare too many variables in the global namespace is the avoid conflicts with code written by others or yourself. Here’s an example to illustrate this:

function foo() { return 1; }
function bar() { for (i=0; i<5; i++) {} }
 
i = foo();
bar();
 
// what is i here?

In this example, i=5 at the end of execution. This happens because the variable i both inside and outside the function left out the var declaration, thus the engine declares it in the global namespace. And if everyone’s code rely on global variables, you may break someone else’s code accidentally.

Extending the Object prototype

Never, never, never extend Object.prototype. By doing that you could break a lot of code that do things such as for (var a in myObj) – such as jQuery. That is the very reason why Crockford’s jslint promotes the use of hasOwnProperty() check. But IMO that produces ugly code. The better way is to just leave Object.prototype alone.

Using multiple var declarations instead of one

In each scope you can make multiple variable declarations by separating each one with a comma. This makes code more readable, and performs better too (albeit by a very small margin).

// Don't do this
function foo() {
    var x = 1;
    var y = 2;
    var z = 3;
}
 
// Do this
function foo() {
    var x = 1,
        y = 2,
        z = 3;
}

Using new Array() and new Object()

Please don’t declare arrays and hashes like this.

var arr = new Array(),
    hash = new Object();
hash.a = 1;
hash.b = 2;

When you do this instead.

var arr = [],
    hash = { a: 1, b: 2 };

Not making use of truthy/falsey values: undefined, null, false, ”, [], etc.

In JavaScript, a variable’s value can be truthy or falsey. This mean that while the value isn’t strictly equivalent to the boolean values true and false, they can be coerced into a boolean value.

// No need for this!
if (someString != undefined && someString != '') alert(someString);
 
// This gives the same result and is much cleaner
if (!someString) alert(someString);

You can run quick tests in your browser to check if something is truthy or falsey.

var a; // undefined
if (!a) alert('falsey');
if (!'') alert('falsey');
if ([1,2]) alert('truthy');
if (!null) alert('falsey');
if (!0) alert('falsey');
if (100) alert('truthy'); 

Not making use of truthy/falsey values (part 2): for loops

Another great use of truthy and falsey is in a for loop. In most other languages, the exit-check of the loop usually makes sure the index does not go out of bounds. But in JavaScript we can do one better!

// an array of lower-case letters
var arr = ['a', 'b', ..., 'z'];
 
// don't do this
for (var i=0; i<arr.length; i++) {
    // do something with arr[i]
}
 
// do this
for (var i=0, curr; curr=arr[i]; i++) {
   // do something with curr
} 

The second for loop works because arr[i] is undefined if i is an out-of-bounds index, and undefined is falsey. Also, this method performs better (especially in IE 6/7 where arr.length lookup can be costly). Be careful not to use this approach if you know an array may contain a zero (0), or any other falsey values you don’t want to prematurely exit from.

Using switch statements

Update: 2012-02-11

Switch statements have been optimized in modern JavaScript engines. Function hashes are still very useful when you need code reuse, or when to refactor a complex function into smaller, simpler ones.

A lot of times when you use a switch statement in JavaScript, you really should be using function hashes. This is because switch statements in JavaScript don’t perform as well as you’re probably used to in other languages.

// switch statement
var x;

switch (something) {
case 'foo':
    x = 1;
    break;
case 'bar':
    x = 2;
    break;
default:
    x = 3;
}

// function hashes
var handlers = {
    foo: function() { return 1; },
    bar: function() { return 2; },
    _default: function() { return 3; }
};

var x = ( handlers[something] || handlers._default )();

Not making use of truthy/falsey values (part 3): Converting a value using Boolean(x)

Okay, I’m not sure if this counts a an anti-pattern but it’s more of a personal preference. Of course we should never use Boolean('') inside an if-check, but sometimes we want to convert any value into an actual boolean. What you should do instead of using Boolean(x) is to use !!x. This works because !x returns true if x is falsey, and false otherwise. We then negate that boolean again to get what we want. 

Using for-in loop over an array

Arrays in JavaScript are special objects, so a for-in loop doesn’t do what you think it does.

var arr = ['foo', bar', 'faz', baz'];
for (var item in arr) {
   // what is item here?
}

You may think you'll get the values of the array above, but you actually get the indices inside the array. It’s easier just to stick to normal for loops.



blog comments powered by Disqus