A member function's this is modified when called via an event

I’m having trouble understanding how ‘this’ works in JS/Playcanvas with events. When I call a member function of a ES6+ class directly, ‘this’ points to the instantiated object of the ES6 class. When I make the member function act as a listener to a PC event, ‘this’ suddenly points to the global ‘Application’ object. Is there a way to make it so ‘this’ points to the instantiated object in both cases? Why does this happen in the first place, is it because it could bypass the lifetime of the instantiated object?

Thanks.

    constructor(data){
        //various constructor code goes here
	//
	//------

        //direct call 
        this.OnBarModified(character);
        pc.events.attach(this);
        //make this.OnBarModified member function a listener
        pc.app.on('barModified', this.OnBarModified);

    }

OnBarModified(modifiedBar) {
        //when this is called in the constructor directly, this points to the costumeUI instance that has been instantiated as inspected....
//when this is called as a listener by the 'modifiedBar' event, this points to the global 'Application'.... which is not what i want.
	console.log(this.data.name + 'attached to' + modifiedBar + 'may have been modified');
    }

}```

Hi @charles.yanmiller and welcome,

I think you are on the right track to understand how that works. this is a JS internal keyword used to get access to the instance of the object he current code context is running on.

PlayCanvas events allow you to optionally set the scope by adding it as the third parameter when attaching the event listener. But if you don’t specify a scope, then PlayCanvas by default selects the object the event is firing on (e.g. application or entity or script instance).

You can study the source code of the event system here: https://github.com/playcanvas/engine/blob/f6f1461724acb954bfc3fce53cb91bf96f2a51a2/src/core/event-handler.js#L79

In your case I think you just need to specify the scope like this:

pc.app.on('barModified', this.OnBarModified, this);
2 Likes

Thanks this is exactly what I was looking for.

I didn’t realize it was possible to explicitly change the scope in JS.

1 Like