1

I have a class which contains functions and variables such as the following Code:

class Engine {
    private inputHandler: InputHandler;
    private webGl: WebGLRenderingContext;
    private timeStep: number = 1000 / 60;
    private delta: number = 0;
    private lastFrameTimeMs: number = 0;

    constructor() {
        this.webGl = Canvas.initWebGL(window.innerWidth, window.innerHeight);
        this.inputHandler = new InputHandler();
    }

    private draw() {
        // stuff happening here
    }

    private update(delta: number) {
        // stuff happening here
    }

    public run(timestamp: number) {
        console.log('this: ', this);
        this.delta = timestamp - this.lastFrameTimeMs;
        this.lastFrameTimeMs = timestamp;

        while(this.delta >= this.timeStep) {
            this.update(this.delta);
            this.delta -= this.timeStep;
        }

        this.draw();

        requestAnimationFrame(this.run);
    }
}

window.onload = () => {
    var engine = new Engine();
    engine.init();
    requestAnimationFrame(engine.run);
}

My problem here is that when I call engine.run in window.onload(), 'this' in the Engine class becomes "Undefiened". One solution is making the variables and functions static and calling Engine.run() etc. but I feel like that is not the way to go.

Is there a particular reason why 'this' poly-morphs in the class if so, why and what would I have to change ?

As a side note: I am converting my .ts classes into .js with npm and bundling them with webpack at the end.

Vitax
  • 21
  • 3
  • Possible duplicate of [requestAnimationFrame scope change to window](https://stackoverflow.com/questions/19707443/requestanimationframe-scope-change-to-window) – zgue Sep 27 '17 at 09:33

1 Answers1

1

The run function is being passed to requestAnimationFrame and isn't being invoked as a method of an object. It is being called as run() instead of engine.run(), so it loses context.

You can retain the context by passing a function which invokes run as a method:

window.onload = () => {
    var engine = new Engine();
    engine.init();
    requestAnimationFrame(() => engine.run());
}

Or by calling bind:

window.onload = () => {
    var engine = new Engine();
    engine.init();
    requestAnimationFrame(engine.run.bind(engine));
}
Frank Modica
  • 10,238
  • 3
  • 23
  • 39