How does scope work in event handlers?

I’m a little confused by the way scope changes in event handlers, specifically the way that “this” doesn’t refer to the object the method is originally part of. For example, suppose I’m defining a Layer like this:

var MyLayer = cc.Layer.extend ({
    ctor:function () {
        this.foo = "bar";
        cc.eventManager.addListener({
        event:cc.EventListener.CUSTOM,
        eventName:"MyEvent",
        callback:this.MyHandler},
        this);
    },
    MyHandler:function(event)
    {
        cc.log(this.foo);   
    }
});

i can trigger the event fine:

   cc.eventManager.dispatchCustomEvent ("MyEvent");

but this.foo is undefined, because “this” doesn’t refer to the MyLayer object anymore, it refers to something else, maybe the event dispatcher? I find this kind of confusing because it cuts the event handlers off from their classes.

I can get around it by accessing the event target:

MyHandler:function(event) {
   var self=event._currentTarget;
   cc.log(self.foo);
}

But that seems awkward and a little confusing to use this and self in different places. Is this the right way to do this, or is there another convention in cocos?

I believe getting the current target is the way this was designed to work. (I use event.getCurrentTarget() because I think that’s more consistent with the concept of using getters/setters.) It might also be more flexible this way, because you could use a function from one object with another.

Nevertheless, not completely sure if this will work, but off the top of my head if you really want to call this.foo in MyHandler, for the listener change callback:this.MyHandler to callback:this.MyHandler.bind(this). This pretty much forces the function’s owner to become this when you run it using that specific reference. (As I said, it’s just off the top of my head, so it might not work.)

But as I said, I think the proper way to do it is by getting the current target, but you’re the programmer so what you rest on is up to you.

thanks - it works ok, just wanted to make sure i wasnt doing it a needlessly complicated way.