我使用这样的代码将参数传递给事件处理函数。但是,在这种特殊情况下,循环会导致问题。在所有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));
}
答案 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));
}
那说我发现使用一个函数更容易读取函数,我认为使用函数作为事件处理程序而不是对象也更常见。