JavaScript Puzzle - The Too Tidy Assignment
Written by Mike James   
Article Index
JavaScript Puzzle - The Too Tidy Assignment
Solution

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 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 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. However:

var a=b+1,b=0;

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

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;

 

Banner

More Puzzles

Sharpen Your Coding Skills
Programmer Puzzle - Hermit Boxes

Can you program a solution to this puzzle  in which you place 3D boxes on a 2D grid to prevent your opponent being able to make a legal move? Let's hear what the team at International Storm Door  [ ... ]


Javascript
Impossible Equalities - a JavaScript puzzle

It is almost folklore that the JavaScript equality operator == is evil and you should always use the strict equality operator === but sometimes it just makes things easier to get JavaScript to do all  [ ... ]


Sharpen Your Coding Skills
Sharpen your Coding Skills - Elevator Puzzle

Introducing Melvin and Bugsy, characters who are the creation of Joe Celko who has joined the team to give you an opportunity to sharpen your coding skills with puzzles that will both amuse and tormen [ ... ]


Other Articles

 

<ASIN:059680279X>

<ASIN:0470526912>

<ASIN:1590597273>

<ASIN:0596806752>



 
 

   
RSS feed of all content
I Programmer - full contents
Copyright © 2014 i-programmer.info. All Rights Reserved.
Joomla! is Free Software released under the GNU/GPL License.