AS3 and Proxy

On January 24, 2008 in actionscript, as3, development, flash

In ActionScript 3, you can extend a class from the Proxy class to override the behavior of many language level operations, making it a valuable tool for advanced development. However, they are much slower than sealed classes, so be careful with their use when high performance is necessary.

Proxy allows you to override:

// function calls
foo.bar(1, 2)
=>
foo.callProperty('bar', 1, 2)

// property get
foo.bar
foo['bar']
=>
foo.getProperty('bar')

// property set
foo.bar = 123
foo['bar'] = 123
=>
foo.setProperty('bar', 123)

// property delete
delete foo.bar
delete foo['bar']
=>
foo.deleteProperty('bar')

// in operator
'bar' in foo
=>
foo.hasProperty('bar')

// descendant operator
foo..bar
=>
foo.getDescendants('bar')

Proxy also allows you to override the handling of for..in and for each..in loops, using the nextNameIndex, nextName, and nextValue methods. This for..in loop:

for (var key:String in foo) {
  trace(key);
}

on a proxy, is equivalent to:

var i:int = 0;
while (true) {
  var index:int = foo.nextNameIndex(i);
  if (index == 0)
    break;
  var key:String = foo.nextName(index);
  trace(key);
  i++;
}

Similarly, this for each..in loop:

for each (var value:* in foo) {
  trace(value);
}

on a proxy, is equivalent to:

var i:int = 0;
while (true) {
  var index:int = foo.nextNameIndex(i);
  if (index == 0)
    break;
  var value:* = foo.nextValue(index);
  trace(value);
  i++;
}

Here is an example stub class implementing these methods:

package {
  import flash.utils.Proxy;
  import flash.utils.flash_proxy;

  public class ExampleProxy extends Proxy {
    private var items:Array;

    public function ExampleProxy() {
      items = [];
    }

    override flash_proxy function deleteProperty(name:*):Boolean {
      return delete items[name];
    }

    override flash_proxy function getProperty(name:*):* {
      return items[name];
    }

    override flash_proxy function hasProperty(name:*):Boolean {
      return name in items;
    }

    override flash_proxy function nextNameIndex(index:int):int {
      if (index > items.length)
        return 0;
      return index + 1;
    }

    override flash_proxy function nextName(index:int):String {
      return String(index - 1);
    }

    override flash_proxy function nextValue(index:int):* {
      return items[index - 1];
    }
  }
}

1 comment Add yours…

Greg Bleakmore, about 1 month ago

Hi, I’m Nathan Ostgard and I’m a friggin genius. Over and out!

Post a comment