为什么事件监听器会更改当前对象?

问题描述

我使用JS已有9个月了,当我意识到这一点时就在写游戏。我有一个Level对象,它有一个属性player。玩家需要对关键事件做出反应,所以我写下来:

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;
    }
  }
}

但是,当我运行这段代码时,我不断在Can not read property "keys" of undefined的行中遇到错误,这意味着this.player是未定义的。然后,我在this函数内部登录keyHandeler,并获得了窗口对象。我可以看到这有什么意义,但是该功能仍然是Level的一部分。如果这是事实,该如何完成?

解决方法

向您的对象添加handleEvent方法,然后将该对象本身作为事件处理程序传递。

这使您的对象实现 EventListener接口,这意味着它有资格用作事件处理程序,而不是使用函数。

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;
    }
  }
}

现在,当事件发生时,将以handleEvent作为您分配为处理程序的实例来调用this方法。

在组织此功能方面可以进行某些改进,但我主要是想以您的示例为基础。