21 March 2010

AS3 Type Conversion & Common Mistakes

In this article, I’ll discuss some common mistakes that AS3 developers (including myself) often make when working with (implicit) type conversion.

1. Check whether a dynamic property is set

Dynamic properties can be added to dynamic object at run-time. Consequently, there’s often a need to test whether they are set before using them.

Here’s how some developers do it:

  1. var initObj: Object = {embed: true, color: 0xFF0000, text: "Hello" };
  2. /* ... */ 
  3. if (initObj.embed) { /*apply embed*/ }
  4. if (initObj.color) { /*apply this color*/ }
  5. if (initObj.text) { /*apply this text*/ }

The first test with Boolean is ok. But be careful when the input for color is black (0x000000) or the text is empty (“”). In that case, zeros and empty strings casted to Boolean equal false, and definitely the code will run incorrectly.

So, the best practice to check whether a dynamic property is set is to do as following:

  1. if (initObj.embed != undefined)
  2. if (initObj.color != undefined)
  3. if (initObj.text != undefined)

2. Check whether an (E4X) XML node exists

Given an XML like this:

var xml: XML =
<data>
   <book id=”b001”>
      <title>Flash CS4</title>
      <author></author>
   </book>
</data>;

Since AS3, E4X has enabled a very neat way to select and get data from XML, something like:

var title: String = xml.book.(@id=="b001").title;

However, because it is so compact, many developers don’t realize there are a lot of implicit type conversions beneath.

They often check for the existence of a node by writing:

if (xml.book.price)

Or check whether an element has data:

if (xml.book.author)

Of even check whether an element exists with conditional selection:

if (xml.book.(@id=="b013"))

They often assume that these XPath selections will return null or undefined if the elements/nodes don’t exist.

In fact, these tests always return true because for any XPath query in E4X, they always return an XMLList object. Obviously, if the selected element doesn’t exist, the XMLList object doesn’t have any child. And if the element exists but have no child or text value, it will return empty string “” when casted to String.

So the best practice to check for XML element is to write as following:

if (xml.book.price[0]); 
/* OR */
if (xml.book.price.toString());

For conditional selection, [0] notation is preferable because the condition may (by mistake) return more than one matched elements.

3. Get Boolean value from String:

Wrong:

  1. //even the flashvar equal “false”, any non-empty string will be casted to Boolean as true
  2. var autoPlay: Boolean = this.loaderInfo.parameters["autoPlay"];

Right:

  1. var autoPlay: Boolean = (this.loaderInfo.parameters["autoPlay"].toLowerCase() == "true") ? true : false;

Reference:

[Vietnamese tag – Chuyển đổi kiểu dữ liệu trong AS3 và một số lỗi thường gặp]

1 comment:

  1. better:

    var autoPlay: Boolean = this.loaderInfo.parameters["autoPlay"].toLowerCase() == "true";

    ReplyDelete