Как использовать метод класса внутри функции обратного вызова в actionscript? - PullRequest
0 голосов
/ 13 сентября 2011

Когда вы вызываете метод класса внутри функции обратного вызова, вы не можете использовать this object.
Чтобы вызвать метод, в javascript я объявляю переменную that, присваиваю this that и использую that внутри обратного вызова для вызова метода this.

Должен ли я делать в Actionscript так же, как в JavaScript?

Следующий код является примером использования that для вызова метода внутри обратного вызова.
Есть ли более простой способ в ActionScript?

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 ]

6 голосов
/ 13 сентября 2011

Если вы сделаете вашу функцию обратного вызова методом класса 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 и его области действияэто целый класс.

5 голосов
/ 14 сентября 2011

Вот еще один способ сделать это:

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 голосов
/ 14 сентября 2011

Это не ответ, но больше объясняет, почему встроенные замыкания являются утечкой памяти, из запроса комментария @js _.

Управление памятью во Flash осуществляется 2 способами; подсчет ссылок, маркировка и развертка (для получения более подробной информации ознакомьтесь с http://divillysausages.com/blog/tracking_memory_leaks_in_as3).

Утечка памяти происходит из-за вызова addEventListener(). По умолчанию addEventListener создаст ссылку на объект, который он слушает - как, например, ваша анонимная функция будет содержать ссылку на ваш объект.

Вы можете сделать его слабым слушателем, но поскольку ваша функция анонимна, у нее нет других ссылок, а это означает, что, если вы прослушиватель событий был слабым, все это будет собрано в конце функции (то же самое, если вы использовали локальная переменная).

Итак, чтобы заставить работать анонимные функции, вам нужно сделать слушателя события сильным. Но когда вы пришли, чтобы удалить слушателя, вы не можете получить доступ к анонимной функции, поэтому вы не можете удалить ее. В лучшем случае вы теряете память, выделенную для обратного вызова. В худшем случае ссылка на ваш объект анонимной функцией означает, что сам объект никогда не будет собран (что может привести к цепочке), поскольку Flash считает, что он все еще используется.

Если сам объект в конечном итоге не имеет других ссылок, кроме прослушивателя событий, то оба должны быть собраны во время фазы метки и развертки (так как это было разработано с учетом таких циклических ссылок). Тем не менее, вы никогда не хотите, чтобы метка и развертка запускались - это чертовски медленно (вы, вероятно, будете часто замечать паузу в своей программе) и только когда оно начнется, когда использование памяти начнет выходить из-под контроля. Вы хотите контролировать подсчет ссылок самостоятельно

2 голосов
/ 13 сентября 2011

См. Документация по функциям на сайте Adobe. Используйте apply с «thisArg», равным объекту, для которого вы хотите вызвать функцию-член, и «this» будет правильным.

1 голос
/ 13 сентября 2011

Вы используете закрытие встроенной функции, поэтому искомый 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
Закрытие функций
Слушатели событий

0 голосов
/ 13 сентября 2011

Если вы сделаете трассировку (это), она скажет что-то вроде [функция Global].Вот почему это не работает.

...