开发者

How to use a method of a class inside a callback function in actionscript?

When you call a method of a class inside a callback function, you can not use this object.

To call the method, in javascript, I declare that variable, assign this to that, and use that inside the callback to call the method of this.

In actionscript, do I have to do the same way as I do in javascript?

The following code is the example to use that to call a method inside callback.

Are there more simple way in actionscript?

class C {
    private var that:C;

    function C() {
        that = this
    }

    public function f1():void {
        var sp:Sprite = new Sprite;

        sp.addEventListener(MouseEvent.CLI开发者_StackOverflow社区CK, function():void {
            this.f2(); // this doesn't work
            that.f2(); // that works
        });
    }

    public function f2():void {
        trace('hello');
    }
}


If you make your callback function a method of the class C, you will be able to access this.

 public class C
 {
     private function f1():void
     {
         var sp:Sprite = new Sprite();

         sp.addEventListener(MouseEvent.CLICK, callback);
     }

     private function callback(event:MouseEvent):void
     {
         this.f2();
     }

     private function f2():void
     {
         trace("Hello World");
     }
}

Now this refers to the instance of the class C and its scope is the whole class.


Here's another way to do that:

package some.package {
    class SomeSprite extends Sprite {
        public function f1():void
        {
            var sprite1:Sprite = new Sprite;
            sprite1.addEventListener(MouseEvent.CLICK,
                (new Closure(f2, this, ["Hello"], sprite1).handler));

            var sprite2:Sprite = new Sprite;
            sprite2.addEventListener(MouseEvent.CLICK,
                (new Closure(f2, this, ["Bye Bye"], sprite2).handler));
        }

        private function f2(message:String):void
        {
            trace(message);
        }
    }
}

class Closure {
    public var callback:Function;
    public var thisObj:Object;
    public var params:Array;
    public var dispatcher:IEventDispatcher;
    public var cleanAfterCallback:Boolean = true;

    function Closure(callback:Function, thisObj:Object, 
        params:Array, dispatcher:IEventDispatcher)
    {
        this.callback = callback;
        this.thisObj = thisObj;
        this.params = params;
        this.dispatcher = dispatcher;
    }

    public function handler(e:Event):void
    {
        callback.apply(thisObj, params);

        if (cleanAfterCallback)
            dispatcher.removeEventListener(e.type, eventHandler)
    }
}


See the Function Documentation on Adobe site. Use apply with "thisArg" equal to the object on which you want to invoke the member function and "this" will be correct.


You are using an inline function closure, so the this you are looking for will not be in that scope. It is very similar (if not the same) to function closures in javascript. The above method is fine. There are other ways to do this but there are not necessarily simpler, it depends on your implementation.

function():void {
        this.f2(); // this is scoped only to within this function
        that.f2(); // that has reference to the global object this
} 

Please read the following in the ActionScript Documentation
Function Closures
Event listeners


This isn't an answer, but is more to explain why inline closures are a memory leak, from a comment request by @js_.

Memory management in Flash is done 2 ways; reference counting and mark and sweep (check out http://divillysausages.com/blog/tracking_memory_leaks_in_as3 to go more in-depth).

The memory leak comes from the addEventListener() call. By default, addEventListener will create a reference to the object that it's listening to - as in, your anonymous function will hold a reference to your object.

You can make it a weak listener, but because your function is anonymous, it has no other references, meaning that if you event listener was weak, it'd all get collected at the end of the function (ditto if you used a local variable).

So, to make anonymous functions work, you need to make the event listener strong. But when you come to remove the listener, you can't get access to the anonymous function, so you can't remove it. Best case scenario, you lose the memory allocated for the callback. Worst case scenario, the reference to your object by the anonymous function means that the object itself never gets collected (which can chain) as Flash thinks it's still in use.

If the object itself eventually has no other references, other than the event listener, then both should get collected during the mark and sweep phase (as this was designed with such circular references in mind). That said, you never really want mark and sweep to kick in - it's slow as hell (you'll probably notice a pause every so often in your program) and only ever starts when your memory usage starts to get out of hand. You want to control reference counting yourself


If you do a trace(this), it will say something like [function Global]. That is why it does not work.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜