将函数分配给事件处理程序后,变量会不断更改

时间:2010-10-30 23:49:00

标签: javascript json

我在页面上有一堆元素,所有ID都存储在一个名为 ids [] 的数组中。

我为这些div中的每一个初始化了一个第三方DOM脚本,用于检测元素何时被拖动。下一步是为每个元素的onDrag事件分配一个函数。

为简单起见,我只想显示一个弹出对话框,其中说明了被拖动元素的ID。我按如下方式遍历我的数组:

for (i=0;i<ids.length;i++)
{
document.getElementById(ids[i]).onDrag = function(){alert(ids[i])}
}

这一切似乎都很好,但是切换任何元素的拖动事件会导致弹出一个对话框,指出数组中最后一个元素的ID。换句话说,看起来我的迭代中的上述函数总是被评估为我的数组中的最后一个索引。我觉得我在这里错过了一些非常简单的东西,但这个问题让我疯狂。

2 个答案:

答案 0 :(得分:4)

您遇到的事情称为 closure ,它是Javascript的重要组成部分。

  

闭包是一个表达式(通常是一个函数),它可以包含自由变量以及绑定这些变量的环境(“关闭”表达式)。

分配给ondrag的匿名函数会关闭它的环境,包括变量i。因此,只要i在此函数之外发生更改,i将相应地包含新值。

在当前上下文中解决此问题的方法是使用其他自执行函数创建另一个范围。

for (var i=0; i<ids.length; i++) {
  document.getElementById(ids[i]).onDrag = (function(i){  // <- i is a parameter
    return function() {
      alert(ids[i]);  // <- i will be the inner value saved from outside
    };
  })(i);  // <- invoke immidiately with the i from outside
}

您可以阅读以下主题:Use Cases for JavaScript Closures @kangax

答案 1 :(得分:1)

进行以下更改,

for (...){
    SetOnDrag(ids[i]);
}

function SetOnDrag(id)
{
    document.getElementById(id).onDrag = function() { alert(id); };
}