Javascript 在对象属性上使用事件侦听器是否合适/好主意?

Javascript 在对象属性上使用事件侦听器是否合适/好主意?,javascript,canvas,Javascript,Canvas,我正在用Javascript创建一个HTML5画布蛇游戏,在尝试使我的代码更面向对象时,我遇到了一种情况,我不确定我所做的是否有效 Game.prototype.gameOver = function() { game.isOver = true; clearInterval(intervalId); console.log("Game Over!"); window.addEventListener("keydown",

我正在用Javascript创建一个HTML5画布蛇游戏,在尝试使我的代码更面向对象时,我遇到了一种情况,我不确定我所做的是否有效

Game.prototype.gameOver = function() {
    game.isOver = true;
    clearInterval(intervalId);
    console.log("Game Over!");
    window.addEventListener("keydown", function(e) {
        if (e.code === "Space") {
            game.reset();
        }
    })
}
当蛇与墙或自身碰撞时,将调用game.gameOver()

只需在全局范围级别添加重置eventListener并检查游戏是否结束是更好的方法,还是完全可以

编辑:在发布这篇文章之后,我意识到每次调用gameOver时都会添加一个新的事件侦听器,这就是我的问题的根源。我已经修复了代码,因此事件侦听器的实例一次不会超过一次。

只要在该侦听器启动后再次删除该侦听器,这应该没问题,唯一棘手的一点是,只有以与添加侦听器完全相同的方式删除它,才能删除该侦听器

在此处使用现代JS类语法而不是旧式原型语法:

class Game {
  constructor(...args) {
    // ...
    this.reset();
  }

  reset() {
    this.isOver = false;
    
    // ...

    // If reset() triggered from a window keydown event, remove
    // that keydown listener so it will only kick in once:

    if (this.resetHandler) {
      window.removeEventListener(`keydown`, this.resetHandler);
      this.resetHandler = false;
    }
  }

  gameOver() {
    this.isOver = true;
    console.log(`Game Over!`);

    // Create a function that can handle a keydown event
    // and calls reset() if it's the right key, and bind
    // it so we can remove it later:

    this.resetHandler = (evt) => {
      if (evt.code === `Space`) {
        this.reset();
      }
    };

    window.addEventListener(`keydown`, this.resetHandler);

    console.log(`Press "space" on the page to continue...`);
  }
}

请注意,arrow函数确保
保留为声明时的状态(即该函数运行的
游戏
实例),而不是
函数(evt){…}
,其中
在运行时的作用域是什么(对于事件侦听器,它将是全局范围,即
窗口
).

这不是常见的做法,但也不是错误的做法。addEventListener用于随时随地添加事件。最好有一个密钥处理程序接口,该接口不做任何事情,只设置密钥的状态,然后从中构建逻辑。在这一天,您需要添加其他方式来重新启动游戏(移动?),您也必须更改该部分,但它不应是更改的一部分。最好在重置方法中删除侦听器,如果有其他调用重置,您的处理程序将保留,并且当用户按空格键时,游戏将无故重新启动。是的,这是一个公平点。更新后。