Tech Blog

AS3 - Looping over properties of a class (property enumeration)

Posted At : February 6, 2008 9:00 PM 11 Comments

In AS1 & AS2 you could use a for..in loop to enumerate the properties of an Object for introspection. Given that everything in Actionscript extends the Object class I expected that you could do a for..in loop over the properties of a Class. For example if you wanted to do a loop over all the properties in a value object.

//Sample code to trace the properties of an object
var myVO = new MyVO();
for(i in myVO){
trace(i+':'+myVO[i]);
}

However in AS3 this code will not work as expected (assuming that MyVO is not a dynamic class). I've come across this a couple of times in the last couple of weeks a yesterday found the solution to it.

There is a new function which gives all the introspection data for classes in AS3 - flash.util.describeType() which returns an XML Object.

//Get an XML description of this class
flash.utils.describeType(myVO);

To do the previous looping over the properties it could be used as follows:

//Get an XML description of this class
//and return the variable types as XMLList with e4x
var varList:XMLList = flash.utils.describeType(myVO)..variable;

for(var i:int; i < varList.length(); i++){
//Show the name and the value
trace(varList[i].@name+':'+ myVO[varList[i].@name]);
}

There is one other thing to catch you out though. If you make your variables [Bindable] or use getters & setters they will not show up as "variable". They will show up instead as "accessor" which is something to be aware of.

Hope it helps. Cheers, Mark

11 Comments

Theo 2/7/08 5:40 PM

You could probably do something like this to catch getters, setters and bindable properties too:

var def : XML = describeType(obj);

var properties : XMLList = def..variable.@name + def..accessor.@name;

for each ( var property : String in properties ) {
trace(property + ": " + obj[property]);
}

I haven't compiled nor tested the above, but I have done something similar a few times.

Mark Lynch 2/7/08 8:08 PM

Hi Theo,
Thanks for the tip - I tried it out and it works great. I'm getting to like E4X more the more I use it.

Cheers,
Mark

montana 5/14/08 7:36 AM

muchas gracias! exactly what I was looking for.

Scott Ysebert 5/16/08 10:59 PM

Thanks for this. I was ripping out my hair to try and figure out what was up with AS3 and the ability to loop through my objects properties.

SmartPlugs Design 6/29/08 9:23 PM

This did the trick and worked perfectly! Thanks for posting these!

Joe Shields 9/17/08 4:33 AM

Hi there, just stumbled across this . great stuff helped me alot.

The race outputs them vars in my class but not in the order they are weritten, is there a way to keep them in order ?

Mark Lynch 9/17/08 10:06 PM

Hi Joe,

I didn't figure out if there is a way to get them in the order in which they are declared. I'm not sure if the compiled code retains any information on this - but I really don't know.

Cheers,
Mark

Theo 9/18/08 9:42 AM

It is highly unlikely that the compiled code retains any information about the order in which properties were declared. It has no significance to the running application, and should it happen to exist any hint of the order I'd say it's purely coincidental and could change.

saravana raja 3/9/09 3:12 PM

Mark and Theo
Thanks a lot guys! was knocking my head as i couldn't loop through a TextFormat Object i declared, using for in looping. But found that it works in AS2.

Robert 5/17/09 11:44 PM

My GOD man! Why is everything in AS3 so difficult - there goes 4 hours trying to list my variables! I think I officially HATE AS3. Thanks for the livesaver!

Robert 5/17/09 11:59 PM

here's your methods combined into a single static method that can inspect an object with either degree of detail. I put it into a class called System.

Example:
System.debug_object(my_class_instance, false);

public static function debug_object(o:Object, show_all:Boolean):void {
   import flash.utils.*;
   var def:XML       = describeType(o);
   var props:XMLList    = def..variable.@name;
   if(show_all)       props += def..accessor.@name;
         
   for each (var prop:String in props) {
      trace(prop + ": " + o[prop]);
   }
}

again, great work guys! I can't believe this isn't more readily available!