我可以将“new”匿名函数传递给addEventListener

时间:2010-12-10 19:21:28

标签: javascript events arguments anonymous-function

我使用这样的代码将参数传递给事件处理函数。但是,在这种特殊情况下,循环会导致问题。在所有activeVisual调用中只能访问最后一个linkTags [i]。这与传递参数的匿名函数对于整个循环是一个相同的事实有关。

  for (var i = 0; i < linkTags.length; i++) {
    addCrossEvent(linkTags[i], "click", launchLink);
    addCrossEvent(linkTags[i], "mousedown", 
      function(evt) {
        activeVisual(evt, linkTags[i]);
      });
  }

现在,我记得在匿名函数声明之前尝试添加new:

  for (var i = 0; i < linkTags.length; i++) {
    addCrossEvent(linkTags[i], "click", launchLink);
    addCrossEvent(linkTags[i], "mousedown", 
      new function(evt) {
        activeVisual(evt, linkTags[i]);
      });
  }

它不起作用。 activeVisual永远不会被调用。有人可以向我解释为什么以及如何让它成功呢?

更新最终解决方案

感谢下面的所有回复,我的工作代码现在看起来像这样:

  // Function that provides pass of event handling parameters with separate copy in each loop
  function callbackHandler(index) {
    return function(evt) {
      activeVisual(evt, linkTags[index]);
    }
  }
  ...
  for (var i = 0; i < linkTags.length; i++) {
    ...
    addCrossEvent(linkTags[i], "mousedown", callbackHandler(i));
  }

2 个答案:

答案 0 :(得分:5)

你需要这样做:

addCrossEvent(linkTags[i], "mousedown", 
      (function(i) {
          return function(evt) {
              activeVisual(evt, linkTags[i]);
          }
      )(i);
);

问题在于迭代器变量i在每次迭代时都会发生变化,并且传递了它的引用,i的值不会被复制。将此方式作为参数传递给包装函数,将导致副本,并且它将在该特定迭代时接收实际值。

答案 1 :(得分:2)

为了完整起见,这里解释了为什么使用new的方式无效:

当您使用new调用函数时,该函数会生成一个空对象(您可以在函数内部引用this并从函数原型继承)并返回它。 /> 所以你实际上并没有将函数作为回调处理程序传递,而是函数返回的对象。

只要对象实现EventListner interface以便可用作事件处理程序,这不是问题。如果你这样做,你可以使用你的代码进行一些修改:

  for (var i = 0; i < linkTags.length; i++) {
    addCrossEvent(linkTags[i], "click", launchLink);
    addCrossEvent(linkTags[i], "mousedown", 
      new (function(index) {
        this.handleEvent = function(evt) {
            activeVisual(evt, linkTags[index]);
        }
      })(i));
  }

这实际上类似于@Luca的答案,因为i的值是在创建对象时捕获的。上面的代码实际上与:

相同
function CallbackHandler(index) {
    this.handleEvent = function(evt) {
        activeVisual(evt, linkTags[index]);
    }
}

for (var i = 0; i < linkTags.length; i++) {
    addCrossEvent(linkTags[i], "click", launchLink);
    addCrossEvent(linkTags[i], "mousedown", new CallbackHandler(i));
}

那说我发现使用一个函数更容易读取函数,我认为使用函数作为事件处理程序而不是对象也更常见。

Working DEMO