Javascript 为什么';你不能删除列管者的工作吗?

Javascript 为什么';你不能删除列管者的工作吗?,javascript,event-handling,event-listener,Javascript,Event Handling,Event Listener,我不确定这里出了什么问题,但在chromium和firefox中进行测试时,我发现我在javascript中从元素中删除EventListener是错误的 上下文是一个画布游戏。首先,会显示一个启动屏幕,您可以单击此处开始游戏。单击开始后,我想删除侦听器 主要关注点是startName函数中的removeEventListener。它不会抛出错误。代码执行(我在控制台中看到游戏开始消息,我可以看到“this”就是游戏实例)。我完全搞不懂为什么每次我都要点击画布。预期的行为是,一旦删除EventL

我不确定这里出了什么问题,但在chromium和firefox中进行测试时,我发现我在javascript中从元素中删除EventListener是错误的

上下文是一个画布游戏。首先,会显示一个启动屏幕,您可以单击此处开始游戏。单击开始后,我想删除侦听器

主要关注点是startName函数中的removeEventListener。它不会抛出错误。代码执行(我在控制台中看到游戏开始消息,我可以看到“this”就是游戏实例)。我完全搞不懂为什么每次我都要点击画布。预期的行为是,一旦删除EventListener,单击此处将什么也不做

救命啊

进一步资料:

我还有一个版本,其中非工作删除被写为:

this.c.removeEventListener('click',this.startGame,true);
与上面引用的代码的行为相同


编辑:回复mczepiel的第一个答案

我试图实现你的答案,如下所示:

Typer.prototype.setSplash = function() {
  if (this.bgReady) {
    this.ctx.drawImage(window.t.bgImage, 0, 0);
    this.ctx.font="48px Helvetica";
    this.ctx.textAlign = "center";
    this.ctx.fillStyle="rgb(0,0,255)";
    this.ctx.fillText("Click To Start",310,240);
    var boundFunction = this.startGame.bind(this);
    document.getElementById("cnvs").addEventListener(
      'click',boundFunction,true,boundFunction);
  } else {
    // since setSplash is an early function 
    // wait a bit for the background image and then try again 
    setTimeout(this.setSplash.bind(this),100);
    console.log("bgImage not ready...");
  }
}

Typer.prototype.startGame = function(boundFunction) {
  console.log("game starting ...");
  console.log(this);  // strangely, now this is an Object rather 
                      // than Game, it still has the properties of 
                      // Game tho

  // step 1, remove the click listener for this function

  // still isn't working... 
  document.getElementById("cnvs").removeEventListener(
    'click',boundFunction,true);
}

我想我理解你的建议,但也许不理解。上面的代码仍然没有删除侦听器。非常感谢您的帮助。

您需要存储对调用
this.startName.bind(this)
的结果的引用,并将相同的值传递给
addEventListener
removeEventListener

remove调用希望删除与作为侦听器添加的对象完全相同的对象

如果您想在不同的版本中看到相同的问题,可能会重复和其他问题

编辑未经测试的即兴建议:

Typer.prototype.setSplash = function() {
  if (this.bgReady) {
    // draw stuff

    var canvasElement = document.getElementById("cnvs");
    var dismissSplash = function (evt) {
        canvasElement.removeEventListener('click', dismissSplash, true);
        this.startGame();
    }.bind(this);

    canvasElement.addEventListener('click', dismissSplash, true);
  } else {
        // try to show splash later
    }
}

Typer.prototype.startGame = function() {
    // start game
}

您需要存储对调用
this.startName.bind(this)
的结果的引用,并将相同的值传递给
addEventListener
removeEventListener

remove调用希望删除与作为侦听器添加的对象完全相同的对象

如果您想在不同的版本中看到相同的问题,可能会重复和其他问题

编辑未经测试的即兴建议:

Typer.prototype.setSplash = function() {
  if (this.bgReady) {
    // draw stuff

    var canvasElement = document.getElementById("cnvs");
    var dismissSplash = function (evt) {
        canvasElement.removeEventListener('click', dismissSplash, true);
        this.startGame();
    }.bind(this);

    canvasElement.addEventListener('click', dismissSplash, true);
  } else {
        // try to show splash later
    }
}

Typer.prototype.startGame = function() {
    // start game
}

this.startGame!==this.startGame.bind(this)
elclars:的确。但我不认为这有什么关系。我使用.bind(this)是因为我希望startGame中的上下文是游戏对象,而不是画布元素。
this.startGame!==this.startGame.bind(this)
elclars:的确。但我不认为这有什么关系。我使用.bind(这个)是因为我希望StartName中的上下文是游戏对象,而不是画布元素。啊哈,我想我现在明白你的意思了。类似于'boundFunction=this.startName.bind(this);'然后使用boundFunction作为添加和删除的参数。我要试试看!我编辑了这个问题,以显示我试图实现您的答案。我一定没有理解一些微妙之处,因为侦听器仍然没有被删除。
boundFunction
是一个局部变量,仅存在于
setSplash
函数的范围内;它在
startName
中未定义。您需要将其存储为
this.boundFunction
,例如,在需要它的两个函数中都可以访问它的某个地方。(您也可以在
setSplash
的同一个闭包中执行删除操作,并且只有在删除侦听器之后,才能调用
startGame
Aha,是的,使用这个.boundFunction让我开始了。我试图传递boundFunction,但是,唉,我想是相同的错误导致我无法在第一个pl中删除侦听器ace.我想你可能是对的,在“setSplash闭包”中删除会更优雅,但我不得不承认我不确定这个术语的意思。对此的任何澄清都将不胜感激。啊哈,我想我现在明白你的意思了。类似于'boundFunction=this.startGame.bind(this)的东西;'然后使用boundFunction作为添加和删除的参数。我会尝试的!我编辑了这个问题以显示我试图实现您的答案。我一定没有理解一些微妙之处,因为侦听器仍然没有被删除。
boundFunction
是一个局部变量,它只存在于
setSplash
fun的范围内Action;它在
startName
中是
未定义的
。您需要将其存储为
this.boundFunction
,例如,您可以在需要它的两个函数中访问它的某个地方。(您也可以在
setSplash
的同一个闭包中执行删除操作,并且只有在删除侦听器之后,才能调用
startGame
Aha,是的,使用这个.boundFunction让我开始了。我试图传递boundFunction,但是,唉,我想是相同的错误导致我无法在第一个pl中删除侦听器ace.我认为你可能是对的,在“关闭setSplash”中删除会更优雅,但我必须承认,我不确定这个术语的含义。对此的任何澄清都将不胜感激。