如何在actionscript中的回调函数中使用类的方法?

时间:2011-09-13 04:33:35

标签: flash actionscript-3 actionscript callback event-listener

在回调函数中调用类的方法时,不能使用this对象 要在javascript中调用该方法,我声明that变量,将this分配给that,并在回调中使用that来调用this的方法。

在动作脚本中,我是否必须像在javascript中那样做?
以下代码是使用that在回调内调用方法的示例 动作中有更简单的方法吗?

class C {
    private var that:C;

    function C() {
        that = this
    }

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

        sp.addEventListener(MouseEvent.CLICK, function():void {
            this.f2(); // this doesn't work
            that.f2(); // that works
        });
    }

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

6 个答案:

答案 0 :(得分:6)

如果您将回调函数设为C类的方法,则可以访问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");
     }
}

现在this引用了类C的实例,其范围是整个类。

答案 1 :(得分:5)

这是另一种方法:

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)
    }
}

答案 2 :(得分:2)

请参阅Adobe网站上的Function Documentation。使用apply“thisArg”等于你想要调用成员函数的对象,“this”将是正确的。

答案 3 :(得分:2)

这不是一个答案,但更多的是解释为什么内联闭包是一个内存泄漏,来自@js _的评论请求。

Flash中的内存管理有两种方式;引用计数和标记和扫描(查看http://divillysausages.com/blog/tracking_memory_leaks_in_as3以获得更深入的内容)。

内存泄漏来自addEventListener()电话。默认情况下,addEventListener将创建对其正在侦听的对象的引用 - 例如,您的匿名函数将保存对对象的引用。

你可以把它变成一个弱的监听器,但因为你的函数是匿名的,所以它没有其他的引用,这意味着如果你的事件监听器很弱,它会在函数结束时被收集(如果你使用的话,也是如此)一个局部变量)。

因此,要使匿名函数起作用,您需要使事件侦听器变得强大。但是当你来删除监听器时,你无法访问匿名函数,所以你无法删除它。最好的情况是,您丢失了为回调分配的内存。最糟糕的情况是,匿名函数对您的对象的引用意味着当Flash认为它仍然在使用时,对象本身永远不会被收集(可以链接)。

如果对象本身最终没有其他引用,除了事件侦听器之外,那么两者都应该在标记和扫描阶段收集(因为这是设计时考虑到这样的循环引用)。也就是说,你从来没有真正想要标记和扫描 - 它很慢(你可能会注意到你的程序中经常出现暂停)并且只有在内存使用开始失控时才开始。你想自己控制引用计数

答案 4 :(得分:1)

您正在使用内联函数闭包,因此您要查找的this将不在该范围内。在javascript中函数闭包非常相似(如果不相同)。上面的方法很好。还有其他方法可以做到这一点,但不一定更简单,这取决于您的实现。

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

请阅读ActionScript文档中的以下内容 Function Closures
Event listeners

答案 5 :(得分:0)

如果你做了一个跟踪(这个),它会说[function Global]。这就是为什么它不起作用。