Javascript declarations and assignments

This week I was chasing a javascript bug. At qualys we heavily rely on extjs, and we have a few thousands javascript files that have to live together. The bug ended up being in the following lines:

    ...
    renderer: function(layer, text){
        var tag = node = Ext.apply({
            color: '#FCFCFC',
            background: '#666666'
        }, layer);
        tag.text = tag.text || text;
        if(node.disabled){
            tag.style = "color: #CCC !important";
        }
        return tag;
    },
    ...

Can you see what’s wrong?

The issue comes from the first line, an unconvenient mix of declarations and assignments:

var tag = node = Ext.apply({...})

The developer thought he was initializing 2 local vars called tag and node.

Let’s take something simple:

    function test(){
        var a = b = 2;
        alert(a, b);
    }
    test();
    alert(b);

In the first line, javascript starts by evaluating b = 2. This is an assignment of 2 to the variable b. Because b does not exist, javascript creates a new global variable b and attaches it to the current context, window. (note that this would throw a ReferenceError exception if we were in strict mode).

A quick ref to ECMA-262 shows that assignments return the value that was just assigned. You can double check that in your console eval(b = 2); returns 2.

So now the compiler has evaluated the first expression and now reads var a = 2 since 2 was evaluated. This correctly creates a local variable a containing the value 2 through a declaration, or more precisely a VariableStatement. note that eval(var b = 2); returns undefined.

Anyways… don’t mix up var a = [value] with a = [value] as they are completely different expressions that evaluate to different values and can create unexpected surprises…