IceCreamYou/MainLoop.js

Using a class method as function for "Update" or "Draw"

Closed this issue · 2 comments

Hello !

I'm having a problem with the Update function.
Let's say I have a class named "Game" which has a method named "update"
Normally, I could do this :

let game = new Game();
game.update();

and the method could be like this :
update() {
this.objects.doStuff();
}

But when I try to call the method with the Update call, I can't access "this"
I get the following error : this is undefined

Is it due to the plugin implementation or is this simple javascript behaviour that I'm not aware of ?

Thank you very much.

Ok I found the solution myself by looking at #18

MainLoop.setUpdate(delta => {game.update();});
instead of
MainLoop.setUpdate(game.update);

I don't really get it but I think it might be related to the call with parenthesis ?

Just to be clear what's happening, if you have an ES6 class like this:

class MyClass {
	method1() { console.log(this); }
	method2 = () => { console.log(this); }
}

Functions written as methods or using the function keyword have their own this context, whereas arrow functions use the surrounding this context. So:

const mc = new MyClass();
const m1 = mc.method1;
m1(); // prints `undefined` because the method is called without the `mc` context
mc.method1(); // prints mc
const m2 = mc.method2;
m2(); // prints mc because the `this` context was captured where `method2` is declared
mc.method2(); // prints mc

So if you want method1 (in this example) to run outside of its class with a specific this, you need to explicitly bind it:

const mc = new MyClass();
const m1 = mc.method1.bind(mc);
m1(); // prints mc

Applying this to your case, you could either wrap your update function as you discovered:

MainLoop.setUpdate(delta => game.update(delta));

or you could bind it:

MainLoop.setUpdate(game.update.bind(game));

or you could change how your method is declared in the first place.