Stuff You Didn't Know
About ActionScript
Christophe Herreman
@herrodius
... or an exploration of the ActionScript 3 language in which
you might discover new things that you were not aware of
and that one day might come in handy, or in which you will
want to scream out WTF's so loud that the whole venue
might think I'm presenting naked whilst in reality you are just
looking at a piece of ActionScript code that is so counter-
intuitive or looks rather puzzling you wonder how anyone
came up with the idea to implement certain parts of the API
this way, which on the other hand makes the language also
very fun to work with once you know how to deal with these
peculiarities and it becomes clear that ActionScript is
actually pretty cool and powerful ...
About me
Run Stack & Heap, a development, consulting and training
company based in Belgium specializing in Web / RIA
Development
Certified expert Flex with AIR, loved Flash since 1999
Founder of Spring ActionScript and AS3Commons
Apache Flex committer
Equality "=="
Complex data types are compared by reference, not value.
var a:Array = [1, 2, 3];
var b:Array = [1, 2, 3];
a == b // false
var c:Array = a;
a == c // true
Conditional "?:"
Known as the Ternary Operator.
var result:Boolean = (a > b) ? x : y;
// shorthand for
var result:Boolean;
if (a > b) {
result = x;
} else {
result = y;
}
Logical OR "||="
function (a:Object) {
a ||= new Object();
}
// shorthand for
function (a:Object) {
if (a === null) {
a = new Object();
}
}
Logical AND "&&="
function toHTMLTag (s:String) {
s &&= "<" + s + ">";
return s;
}
// shorthand for
function toHTMLTag (s:String) {
if (s !== null && (s.length > 0))
s = "<" + s + ">";
return s;
}
"as"
Casts a value to another data type, returning null if the cast
fails.
"hello" as String // "hello"
5 as String // null
true as MyClass // null
String("hello") // "hello"
String(5) // "5"
MyClass(true) // Runtime Error
"is" vs "instanceof"
Check if a value is of a certain data type.
var s:Sprite = new Sprite();
s is Sprite // true
s is DisplayObject // true
s is IEventDispatcher // true
s instanceof Sprite // true
s instanceof DisplayObject // true
s instanceof IEventDispatcher // false
"::" name qualifier
Identifies the namespace of an object.
public namespace Dutch;
public namespace French;
Dutch function hello():String {
return "hallo";
}
French function hello():String {
return "bonjour";
}
"::" name qualifier
"public", "private", "protected", "internal"
are also namespaces.
public function get a():String;
private function set a(value:String);
trace(a) // compile error
a = "hello" // compile error
trace(public::a)
private::a = "hello"
"in" vs Object.hasOwnProperty
Check if an object contains a certain
property.
"CASEINSENSITIVE" in Array // true
"CASEINSENSITIVE" in [] // false
"length" in Array // true
"length" in [] // true
[].hasOwnProperty("CASEINSENSITIVE") // false
[].hasOwnProperty("length") // true
"arguments"
An array available in each function that contains the
arguments passed to the function.
function myFunction (x:int) {
for(var i:uint=0; i<arguments.length; i++){
trace(arguments[i]);
}
}
myFunction(1, 2, 3);
// 1
// 2
// 3
"..." Rest Arguments
Pass an arbitrary number of extra arguments to a function.
function myFunction (x:int, ... rest) {
for (var i:uint = 0; i< rest.length; i++) {
trace(rest[i]);
}
}
myFunction(1, 2, 3);
// 2
// 3
Object creation
var a:Array = new Array();
var a:Array = []; // faster
var o:Object = new Object();
var o:Object = {}; // faster
var v:Vector.<String> = new Vector.<String>();
v.push("a");
v.push("b");
var v:Vector.<String> = new <String>["a", "b"];
Object Copies
Create deep or shallow copies depending on
the scenario.
// deep copy
private function clone(obj:Object):Object {
var bytes:ByteArray = new ByteArray();
bytes.writeObject(obj);
bytes.position = 0;
return bytes.readObject();
}
Events
Always override the "clone" method in an Event subclass.
Prevents runtime type coercion errors when redispatching.
class MyEvent extends Event {
public function MyEvent(data:Object){
_data = data;
}
override public function clone():Event {
return new MyEvent(_data);
}
}
for...in vs. for each...in
var arr:Array = ["a", "b", "c"];
// loops through keys (0, 1, 2)
for ( var i in arr ) {
trace( i );
}
// loop through values ("a", "b", "c")
for each ( var s:String in arr ) {
trace( s );
}
Gotcha: order is not guaranteed, use for loop with counter
trace()
You can pass multiple arguments to the trace() method. No
need to compose a string.
trace(new Date(2012, 4, 22), "Aloha", Math.PI, true);
// Tue May 22 00:00:00 GMT+0200 2012 Aloha 3.141592653589793
true
Labeled Loops
Use "label" on a loop to name it. Useful when breaking from
nested loops.
mainLoop:
for (var i:uint = 0; i<10; i++) {
for (var j:uint = 0; j<10; j++) {
if (i == 5 && j == 7) {
break mainLoop;
}
}
}
Global Functions
Declare a single function in an *.as file and name the file the
same as the function.
// in file: myGlobalFunction.as
package {
function myGlobalFunction():void {
trace("in myGlobalFunction");
}
}
Adding Methods to Built-in Classes
Extend the behavior of built-in classes by adding methods to
the prototype.
Array.prototype.removeItem = function (item:*):void {
var index:int = this.indexOf(item);
if (index > -1) {
this.splice(index, 1);
}
};
var a:Array = [1, 2, 3];
a.removeItem(2);
trace(a); // 1, 3
Casting
var o:MyObject = new MyObject();
var o1:MyObject = MyObject(o);
var o2:MyObject = o as MyObject; // o1 === o2
var a:Array = [1, 2, 3];
var a1:Array = Array(a); // new Array !!!
var a2:Array = a as Array; // a1 !== a2
Also the case with Date and Error classes. Watch out!
Array class
var a:Array = new Array(); // empty array
var a:Array = []; // empty array
var a:Array = new Array(10); // array with length 10
var a:Array = [10]; // array with 1 element: 10
var a:Array = new Array(1, 2, 3); // array with values 1, 2,
3
var a:Array = [1, 2, 3]; // array with values 1, 2,
3
Date class
new Date(); // current date
new Date(2012); // 01/01/1970 01:00:
02
new Date(2012, 1); // 01/02/2012 00:00:00
new Date(2012, 1, 1); // 01/02/2012 00:00:00
public function Date(
yearOrTimevalue:Object,
month:Number, // 0 to 11
date:Number = 1, // 1 to 31
hour:Number = 0, // 0 to 23
minute:Number = 0, // 0 to 59
second:Number = 0, // 0 to 59
millisecond:Number = 0) // 0 to 999
Throwing Parties
You can throw more than just errors.
class AwesomeParty {}
try {
throw new AwesomeParty();
} catch (party:AwesomeParty) {
// go loose at moNo!
}
Practical use?
More info
ActionScript 3 Language Reference
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/
ActionScript 3 Language Specification
http://livedocs.adobe.com/specs/actionscript/3/
Twitter
@herrodius, @stackandheap
Stack & Heap Labs
http://labs.stackandheap.com