AS3, AS2, and JavaScript have some strange rules regarding the initialization of variables. These are shocking and perhaps ridiculous to users of C and Java. This article covers one particularly insane quirk.

One of C’s principles is that uninitialized variables are in an undefined state. This is for performance reasons and stands in contrast to Java, AS2, AS3, and JavaScript where each variable is defaulted to null, undefined, 0, false, or NaN. For more on this, see my article on pointless code. Knowing this, consider the following AS3 code:

function foo(): void
{
	var p:Point;
	p.x = 5;
}

While simple, this illustrates an obvious crash. It would sure be nice if MXMLC would catch this at compile time as it is certainly possible for the compiler to determine that the access of p’s x property is impossible since p is never initialized. Sun’s javac compiler does this very well. MXMLC will not even give a compiler warning about this though, so the problem will be discovered at run time when an error is thrown. Now consider if we swapped the lines in the above function and got:

function foo(): void
{
	p.x = 5;
	var p:Point;
}

This is an even more egregious case! Here, p is used before it is even declared. This is clearly an error and one that can easily be committed when one is moving code around inside a function. It should also be even easier for the compiler to catch such an error. Sun’s javac will catch this and throw a compiler error, but MXMLC will not. I regard this as absurd. MXMLC is generating code that cannot possibly execute successfully and it is trivial to determine this impossibility.

I assume that the reason for this lack of error checking is due to the strange function variable scoping present in JavaScript, AS2, and AS3. That is, all function variables are scoped to the function, regardless of whether they are inside the function block or any sub-block. Consider this function where all these variables are in the same scope:

function foo(): void
{
	var x:int;
	if (false)
	{
		var x:int;
	}
	for (var i:int = 0; i < 3; ++i)
	{
		var x:int;
	}
	while (false)
	{
		var x:int;
	}
	switch (3)
	{
		case 2:
			var x:int;
			break;
	}
}

This too, to me at least, seems absurd. The classic nuisance case is when you write two for-loops:

function foo(arr:Array): void
{
	for (var i:int = arr.length-1; i >= 0; --i)
	{
	}
 
	// Here the iterator i clashes with the iterator in the first loop
	for (var i:int = 0; i < arr.length; ++i)
	{
	}
}

Why these languages chose to scope their function variables like this, I don’t know. I have not yet run across a case where this is helpful and have often run across cases where this is annoying and requires me to move variable declarations away from where they are used and into the function’s main block. Always keep this in mind when you’re writing functions. Sometimes you get a warning, like in the case of the two loops above, and sometimes you don’t, like in the initialization cases above. Worryingly, the cases where you don’t get a warning are the cases that result in the most harm: a run time error.

As always, be vigilant. As a programmer of AS2, AS3, or JavaScript, your tools are less than helpful here.