开发者

Can I pass "new" anonymous function to addEventListener

I use such code to pass arguments to event handler functions. But, in this particular case the loop is causing problems. Only the last linkTags[i] is accesible in all activeVisual calls. This has to do with th开发者_开发技巧e fact that the anonymous function that passes the argument is one and the same for the entire loop.

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

Now, I remember trying to add new before the anonymous function declaration like this:

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

It did not work. The activeVisual never gets called. Can somebody explain to me why and how can I make it work, please?

UPDATE FINAL SOLUTION

Thanks to all responses below my WORKING code now looks like this:

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


You need to do this:

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

The issue is with the iterator variable i which changes at each iteration, and a reference is passed of it, the value of i is not copied. Passing it this way as a parameter to a wrapper function, will cause a copy and it will receive the actual value at that particular iteration.


For completeness, here is an explanation why your way of using new does not work:

When you call a function with new, the function generates an empty object (which you can refer to with this inside the function and which inherits from the functions prototype) and returns it.
So you actually don't pass a function as callback handler, but the object returned by the function.

This is not a problem as long as the object implements the EventListner interface in order to be usable as event handler. If you do this, you could use your code with some modification:

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

This is actually similar to @Luca's answer, because the value of i is captured upon object creation. The upper code is actually identical to:

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

That said I find the usage of an immediate function that returns a function easier to read and I think using a function as event handler instead of an object is more common too.

Working DEMO

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜