需要param

时间:2017-05-30 08:29:06

标签: javascript addeventlistener createjs

我需要为8个对象(手掌)添加一些监听器。 这些对象是相同的,但行为必须根据其位置进行更改。 我有以下(丑陋的)代码:

root.palmsStatus = ["B","B","B","B","B","B","B","B"];

if (root.palmsStatus[0] !== "N")
  root.game.palms.palm1.addEventListener("click", palmHandler = function(){ palmShakeHandler(1); });
if (root.palmsStatus[1] !== "N")
  root.game.palms.palm2.addEventListener("click", palmHandler = function(){ palmShakeHandler(2); });
if (root.palmsStatus[2] !== "N")
  root.game.palms.palm3.addEventListener("click", function(){ palmShakeHandler(3); });
if (root.palmsStatus[3] !== "N")
  root.game.palms.palm4.addEventListener("click", function(){ palmShakeHandler(4); });
if (root.palmsStatus[4] !== "N")
  root.game.palms.palm5.addEventListener("click", function(){ palmShakeHandler(5); });
if (root.palmsStatus[5] !== "N")
  root.game.palms.palm6.addEventListener("click", function(){ palmShakeHandler(6); });
if (root.palmsStatus[6] !== "N")
  root.game.palms.palm7.addEventListener("click", function(){ palmShakeHandler(7); });
if (root.palmsStatus[7] !== "N")
  root.game.palms.palm8.addEventListener("click", function(){ palmShakeHandler(8); });

我有两个需求:

1)在点击事件中不使用匿名函数。

我写了这段代码,但它没有用

root.game.palms.palm8.addEventListener("click", palmShakeHandler(8));

所以这个工作正常

root.game.palms.palm8.addEventListener("click", function(){ palmShakeHandler(8); });

但我不明白如何删除事件监听器。 我尝试这个解决方案,但它没有工作

root.game.palms.palm8.addEventListener("click", palmHandler = function(){ palmShakeHandler(8); });
root.game.palms.palm8.removeEventListener("click", palmHandler);

2)在for循环中添加和删除监听器

我编写了以下代码,但行为不正确。

  for (i=1; i <= root.palmsStatus.length; i++){
    if (root.palmsStatus[i-1] !== "N"){
      root.game.palms["palm" + i].addEventListener("click", function(){ palmShakeHandler(i); });
    }
  } 

添加了侦听器,但传递给 palmShakeHandler 的参数值始终为8。

没人能帮我解决这些问题?

3 个答案:

答案 0 :(得分:4)

使用Function.prototype.bind方法在JavaScript中实际上有一种完美的方法。

bind允许您定义将作为参数传递的额外参数。

您还应该记住bind创建一个新函数,而不是修改初始函数。

这是它的样子:

function palmHandler(number) {
  // your code working with `number`
}

var palmHandler8 = palmHandler.bind(null, 8)
// the palmHandler8 is now tied to the value 8.
// the first argument (here null) define what `this` is bound to in this function

这应该可以解决您的问题,并且您可以轻松删除处理程序:)

您的代码如下所示:

for (i=1; i <= root.palmsStatus.length; i++){
  if (root.palmsStatus[i-1] !== "N"){
    root.game.palms["palm" + i].addEventListener("click", palmShakeHandler.bind(null, i));
  }
} 

为了能够在之后删除处理程序,您需要保留对使用bind创建的函数的引用。这将是这样做的方式。

var boundHandler = handler.bind(null, i);
element.addEventListener(boundHandler);
element.removeEventListener(bounderHander);

如果您想了解更多有关JavaScript中令人敬畏的bind方法的信息,那么MDN就是您的朋友:) https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind

顺便说一下,你的函数总是返回8的问题是JavaScript中一个非常常见的问题。这个主题将解释一切(剧透,这是一个范围问题:))https://stackoverflow.com/a/750506/2745879

答案 1 :(得分:0)

在你的上一个解决方案中,你正在为每个函数提供相同的var,这就是使函数与8一起工作的原因,因为它是变量的最后一个值。

要工作arround,你可以使用“let”(请至少使用var,其他人认为“i”是全局的,并且可以在代码中的每个位置更改)但是因为我不知道你的目标浏览器我建议其他解决方案

for (var i=1; i <= root.palmsStatus.length; i++){
    if (root.palmsStatus[i-1] !== "N"){
      root.game.palms["palm" + i].addEventListener("click", (function(index)
      (return function(){ 
        palmShakeHandler(index); 
      }))(i);
    }
  } 

由于它看起来像是针对现代浏览器,我将使用let。https://kangax.github.io/compat-table/es6/

for (var i=1; i <= root.palmsStatus.length; i++){
    let index = i;
    let intermediateFunction = function(){palmShakeHandler(index);};
    if (root.palmsStatus[i-1] !== "N"){
      root.game.palms["palm" + i].addEventListener("click",intermediateFunction);
      root.game.palms["palm" + i].removeHandShake = function(){this.removeEventListener("click",intermediateFunction)};
    }
  } 

所以现在你只需要调用“removeHandShake”并删除监听器

我这里有代码,所以它可以轻松弹出一些小错误

答案 2 :(得分:0)

因此,如果你的“手掌”阵列非常庞大,那么为每个人添加一个事件监听器基本上是一个坏主意,因为这会导致性能缺陷。所以我建议采用不同的方法:

var handlers = [function (e) {}, …, function (e) {}];

root.game.palms.forEach(functiion (palm, idx) {
  palm.setAttribute('data-idx', idx);
});

<palmsparent>.addEventListener('click', function (e) {
  var c = e.target, idx = -1;

  while (c) {
    if (c.hasAttribute && c.hasAttribute('data-idx')) {
      idx = parseInt(c.getAttribute('data-idx'));
      break;
    }
    c = c.parentNode;
  }

  //here you also check for the »palm status«
  if (idx >= 0) {
    handlers[idx](c);
  }
})

一个事件监听器,更容易删除,更好的性能。