0

I've been using JS for a little bit ( 9 months), and was writing a game when I realized this. I had a Level object, which had a property player. The player needed to react to key events, so I wrote this up:

export class Level{
  constructor(){
    this.player = new Player();

    window.addEventListener('keydown', this.keyHandeler);
    window.addEventListener('keyup', this.keyHandeler);
  }
  keyHandeler(event){
    const down = event.type == 'keydown';
    switch(event.keyCode){
      case 37: this.player.keys.left   = down; break;
      case 38: this.player.keys.up     = down; break;
      case 39: this.player.keys.right  = down; break;
      case 40: this.player.keys.bottom = down; break;
    }
  }
}

However, when I ran this code I kept getting an error along the lines of Can not read property "keys" of undefined, meaning that this.player was undefined. I then logged this inside of the keyHandeler function, and got the window object. I can see how this might make sense, but the function is still a part of Level. If this is just the way it is, how do I accomplish this?

Bagel03
  • 725
  • 7
  • 22
  • 1
    You need to bind `this` to the class like `this.keyhandler = this.keyHandler.bind(this)` in the constructor – BlackMath Aug 16 '20 at 23:10
  • "*the function is still a part of Level*" - it might be defined as a part of the `Level` class, but that just means it's stored on `Level.prototype`. It is not bound to a particular instance. – Bergi Aug 16 '20 at 23:26

1 Answers1

0

Add a handleEvent method to your object, and then pass the object itself as the event handler.

This makes your object implement the EventListener Interface, which means it qualifies for use as the event handler, instead of using a function.

export class Level{
  constructor(){
    this.player = new Player();

    window.addEventListener('keydown', this);
    window.addEventListener('keyup', this);
  }

  handleEvent(event) {
    switch(event.type) {
    case "keydown": case "keyup":
      this.keyHandler(event);
      break
    }
  }

  keyHandeler(event){
    const down = event.type == 'keydown';
    switch(event.keyCode){
      case 37: this.player.keys.left   = down; break;
      case 38: this.player.keys.up     = down; break;
      case 39: this.player.keys.right  = down; break;
      case 40: this.player.keys.bottom = down; break;
    }
  }
}

Now when the event occurs, the handleEvent method will be invoked with this as the instance you assigned as the handler.

There can be certain improvements on organizing this, but I mostly wanted to build on your example.