Variable scope in ActionScript Flex

Hoisting, the strangest ActionScript/Flex “feature” I’ve ever seen (at the moment of writing). Probably you’ve never heard of hoisting. I was hinted to this feature when I had two variables with the same name in one function. Flex was warning about this, but I didn’t really understand why.

Check the following example:

private function existsInSources(searchFor:String):Boolean {
	if(searchFor.length > 10) {
		for each(var valueObj:Object in longStringsCollection) {
			if(valueObj.key == searchFor) {
				return true;
			}
		}
	} else {
		for each(var valueObj:Object in shortStringsCollection) {
			if(valueObj.key == searchFor) {
				return true;
			}
		}
	}
	return false;
}

By default Flex will give the following warning at the second declaration of valueObj, line 9:

3596: Duplicate variable definition.

Coming from other program languages this will (should) strike you as odd behaviour. Both variables ‘valueObj’ exist in their own scope… right?
Not in ActionScript, ActionScript has “Hoisting”.
From adobe.com:

An interesting implication of the lack of block-level scope is that you can read or write to a variable before it is declared, as long as it is declared before the function ends. This is because of a technique called hoisting, which means that the compiler moves all variable declarations to the top of the function.

So basically, the code from the example is transformed to:

private function existsInSources(searchFor:String):Boolean {
	var valueObj:Object;
	var valueObj:Object;
	if(searchFor.length > 10) {
		for each(valueObj in longStringsCollection) {
			if(valueObj.key == searchFor) {
				return true;
			}
		}
	} else {
		for each(valueObj in shortStringsCollection) {
			if(valueObj.key == searchFor) {
				return true;
			}
		}
	}
	return false;
}

“It just shows a warning and doesn’t have any impact on that beautiful piece of code you wrote there, so who gives a ….”.

The problem lies in the fact that this “feature” also means you can refer to objects before they are even initialized.

if(myString.length > 20) {
	trace('Length is over 20!');
} else {
	trace('Length is 20 or smaller');
}
var myString:String = "Hello world!";

Result: a runtime error.

Cannot access a property or method of a null object reference.

Flex compiles (yes, this code compiles fine…) this to:

var myString:String;
if(myString.length > 10) {
	trace('Length is over 10!');
} else {
	trace('Length is 10 or smaller');
}
myString = "Hello world!";

Pay attention to your variable scope, especially when using Flex/ActionScript.

Leave a Reply

Enter the word:

My great (?) anti spam system