Dynamically typed languages are cool until you find (the hard way) some tiny syntax subtlety. JavaScript is no exception to this rule, so having recently wasted a few hours of debugging on what turned out to be an abuse of variable initialisation, I'd like to share some knowledge with you.

Declaring and initialising multiple variables at once

Look at this innocently looking code:

var a = b = 0;
console.log(a, b); // this will output 0, 0 so this syntax is fine, right?

(function () {
  var a = b = 1;
  console.log(a, b); // as expected, this will output 1 1
})();

// now comes the fun part ;)
console.log(a, b); // WTF?? this will print 0 1!

I've deliberately used this statement inside a function body, because this bug feature won't become evident until you try to declare a local variable. Since the assignment operator has a right associativity (i.e. — operands are assigned from the right to the left), it turns out this statement:

var a = b = 1;

is equivalent to this one:

var a = (b = 1);

which in turn is the same as:

var a = (window.b = 1); // or GLOBAL.b if you're using Node to run this

Because of the associativity, you haven't declared b as a local variable, even though you've expected to. So you're implicitly using window.b instead, which will lead to pretty weird and hard to find bugs. As usual, a few saved keystrokes will equal a pretty fun debug session.

So if you are to declare and initialise a few variable at once, use one of these syntaxes:

// this is the best way to do this IMHO
var a = 0,
    b = 0;

// this will work too, but you have to be aware of the assignment order
var a = 0, b = a;

// you can always fail back to multiple statements
var a = 0;
var b = 0;

// or you can declare variables first, then initialise them
var a, b;
a = b = 0;

Accidental assignment

This happens when you write = instead of ==. It is true not only for JavaScript, but also for PHP, C and probably almost every language with a c-like syntax, except Java, where you will get a compilation error.

Take a look at this snippet:

// ...
if (a = 1) {
   // ...
}
// ...

You might have noticed - instead of comparing a with 1, we're actually assigning it! Not only we'll change the value of a, but the code in the block body will execute regardless of what the value of a was! The reason for this is that the value of the expression a = 1 is 1. You can check it:

console.log( a = 1 ) // this will always print 1

You can't always avoid this (unless you have a well tuned linter which is something I'll cover in another post), but in case one of the operands of the comparison is a constant, you can put it on the left side, like this:

if (1 = a) { /* ... */ }
// instead of silently altering the program flow and changing a's value,
// you'll get an error here

if (a = b) { /* ... */ }
// sadly you can't force an error if both the sides of comparison are variables

Bottom line

Of course, these are not the only weird things in JavaScript — it is merely touching the surface! Stay tuned for a post about var hoisting!