JavaScript Puzzle - The Too Tidy Assignment
Written by Ian Elliot   
Article Index
JavaScript Puzzle - The Too Tidy Assignment
Solution

javascriptpuz

Solution

The problem was isolated to a leaking of the local variable out into the global context.

You can see this if you try the following program:

var a=100;
var b=200;
var c=300;
myfunction();
alert(a+","+b+","+ c);

function myfunction(){
 var a=b=c=0;
 alert(a+","+b+","+ c);
}

When the function executes the alert displays 0,0,0 which proves that the variables exist and have been initialized. However the second alert displays 100,0,0 which means that the global variables b and c have been set to zero.

With this information now you should be able to see what is wrong.

JavaScript is a functional language which means that expressions always return a value - even the assignment statement.

So if try:

alert(a=10);

you will see 10 displayed as this is the result of the assignment.

Now consider the evaluation of

var a=b=c=0;

The first part of the instruction is the var statement which declares the a to be a local variable. Next we have the initialization. When you write:

var a=expression;

the order of events is that a is declared, the expression is evaluated and the value assigned to a. In this case we have to evaluate b=c=0. At this point things go wrong. The b variable isn't declared as local, it is a variable used in an expression without being declared, and so it is identified with the global variable b or a new global variable b is created, the same for c. Finally the 0 is evaluated and stored in c, which provides the result to store in b i.e. zero and finally this is also stored in a.

All three variables end up being set to zero but b and c have been used as global variables.

The reason for the error is to think of var as an operator with a higher precedence than assignment. If this were the case then the var would first be applied to create three local variables and then the assignments would be evaluated. However var is not even an operator, let alone having precedence over assignment, it is a statement and it evaluates the assignment before completing and declaring one variable as local. That is

 var a=b=c=0;

 is equivalent to

var a=expression;

and the expression is b=c=0.

Pattern

So it is all JavaScript's fault.

The programmer who attempted to make the simplification of the code was right to be annoyed that JavaScript had broken the rule about not doing unexpected things.

Clearly:

 var a=b=c=0;

should be interpreted to mean:

 var a=0: var b=0; var c=0;

OK, if this is the case what about the programmer who wants to write:

var a=b=c+1;

Does this mean

var a=b; var b=c+1;var c+1;

No, clearly this is not about simple syntactic "sugar". 

Even if you throw in some semantics and say that you don't attempt to declare something that is an expression, i.e. the c+1, you still have a potential problem with:

var b=c+1;

unless you interpret it as

var b=expression;

which is what JavaScript actually does!

For example JavaScript does allow;

var b=0, a=b+1

and this creates both b and a as local variables with b set to zero and a set to 1 i.e. it is equivalent to:

var b=0;
var a=b+1;

However:

var a=b+1,b=0;

doesn't work because b isn't defined when a is initialized i.e.:

var a=b+1;

var b=0;

Finally notice that:

var a,b,c=b=a=0;

does work and creates three local variables initialized to zero.

Can you figure out why?
 (answer at the end)

 

The point is that initialization combined with declaration isn't simple. In compiled languages declaration is a compile time operation and initialization is also usually, but not always, done at compile time. This results in a set of rules for what you can initialize variables to - basically the expression has to have a value at compile time. For example, the simplest thing to do is to restrict initialization to constants - but then the temptation is to extend things to variables with values that can be determined at compile time. This can become very complicated and JavaScript isn't the only language where declaration and initialization are messy.

After you have pointed out what the troublesome expression actually means most JavaScript programmers don't think it's an aberration on the part of JavaScript  - it seems logical.

So how to avoid the problem?

The most obvious way is to understand exactly what every JavaScript statement means in minute detail - obviously not possible.

The alternative is not to try to tidy code to the point where it starts to be a matter of interpretation what the meaning is. In other words if it is a matter of what you expect of an little used construct then don't do it.

Answer to final puzzle:


The reason:

var a,b,c=b=a=0;

works is that a and b are declared as local variables without initialization. Then c is declared as a local variable and set to the result of the expression, which also sets a and b to zero.
That is, the statement is equivalent to:

var a,b;
var c=b=a=0;

 

 

<ASIN:1871962579>

<ASIN:1871962560>

<ASIN:1871962501>

<ASIN:1871962528>

Banner

More Puzzles

Sharpen Your Coding Skills
The Best Sub-Array Problem

At first glance this puzzle seems trivial, all you have to do is find a sub-array, in an array of numbers,  that sums to the largest value. It sounds almost too easy to need a solution, let alone [ ... ]


Javascript
The Undefined Defined Variable

Here's a teaser that poses a practical problem - one that's happened in everyday Javascript programming. See if you can work out the answer before looking at its solution and the pattern to follow to  [ ... ]


Sharpen Your Coding Skills
Towers Of Hanoi Mutants

Towers of Hanoi is a classic puzzle and is often used to illustrate the idea of recursion. Here you are challenged to find solutions to some variations, after first explaining the original version.


Other Articles