为什么我不能向引用Itself的集合中的每个元素添加事件而不是“for(){}”语句中的最后一个元素

时间:2010-04-07 22:09:40

标签: javascript foreach addeventlistener getelementsbytagname

Window加载时,DD内的每个Quote_App元素都应附加onCLick个事件,触发函数Lorem,但Lorem nodeName 1}}返回Id语句中最后一个元素的ForLorem,而不是触发函数的元素的nodeNameId。我希望function Lorem(Control){ /* this.Control=Control; */ this.Amet=function(){ return Control.nodeName+"\n"+Control.id; }; }; function Event(Mode,Function,Event,Element,Capture_or_Bubble){ if(Mode.toLowerCase()!="remove"){ if(Element.addEventListener){ if(!Capture_or_Bubble){ Capture_or_Bubble=false; }else{ if(Capture_or_Bubble.toLowerCase()!="true"){ Capture_or_Bubble=false; }else{ Capture_or_Bubble=true; }; }; Element.addEventListener(Event,Function,Capture_or_Bubble); }else{ Element.attachEvent("on"+Event,Function); }; }; }; function Controls(){ var Controls=document.getElementById("Quote_App").getElementsByTagName("dd"); for(var i=0;i<Controls.length;i++){ var Control=Controls[i]; Event("add",function(){ var lorem=new Lorem(Control); lorem.Control=Control; alert(lorem.Amet()); },"click",Controls[i]); }; }; Event("add",Controls,"load",window); 返回触发该功能的元素的DDLorem

nodeName

目前,您点击任意Id元素DD始终会返回上一个Lorem元素的nodeNameId

Control应该返回触发Control[i]的{​​{1}}(Lorem)的{{1}}和{{1}}。

如何实现这一目标?

谢谢!

3 个答案:

答案 0 :(得分:5)

你需要在循环中使用一个闭包来附加事件处理程序,以便在每次循环迭代中捕获i的值。

  for(var i=0;i<Controls.length;i++) {   
    (function() {
        var Control=Controls[i];

        Event("add",function(){

            var lorem=new Lorem(Control);
            lorem.Control=Control;
            alert(lorem.Amet());

         },"click",Controls[i]);
    })();
  };

这里我使用JavaScript的好朋友,自我调用的匿名函数创建了一个闭包。

需要闭包的原因是没有它,i在执行任何事件处理函数时的值将是最后一次循环迭代中i的值,而不是我们想要什么。我们希望i的值在每个循环迭代中,在我们声明每个事件处理函数的位置,因此我们需要在每次迭代中捕获此值。使用匿名函数,该函数在声明后立即执行,是捕获所需值的良好机制。

另一点,稍微偏离主题,但它可能会帮助你,是每个浏览器不支持事件捕获( ahem ,IE),但事件冒泡是。这有效地使useCapture中的addEventListener布尔标志对于开发跨浏览器Web应用程序毫无用处。因此,我建议不要使用它。

另外一件事,JavaScript通常使用驼峰外壳来表示函数名和变量名。 Pascal大小写通常仅用于构造函数(创建对象的函数)。

答案 1 :(得分:3)

当你创建一个引用它之外的变量的函数时,这些引用将在你调用这个函数时被解析。

在你的情况下:

var functions = [];
function outer() {
    for (var i = 0; i < N; i++) { // <------------
        functions[i] = function() { //            |
            alert(i); // <-- this 'i' refers to this one
        }
    } // At the end of the for loop, i == N (or N+1?)
}
functions[x](); // Will show N (or N+1)
// because that's the current value of i in the outer function
// (which is kept alive just because something refers to it)

你想要做的是在循环的每一步捕获'i'的值,以便以后评估,例如:

var functions = [];
function outer() {
    for (var i = 0; i < N; i++) { // <---------------------------------------
        functions[i] = (function(my_i) { // <----                            |
            return function () { //              |                           |
                alert(my_i); // my_i refers to this which is a copy of 'i' there
            }
        }(i)); // run function(with my_i = the i at each step of the loop)
    }
}
functions[x](); // Will show x

您可以看到有一个内部函数可以将当前计数器的副本作为参数获取。这个内部函数在该副本中保持活动状态,以便以后对存储的innest函数的调用返回创建它的函数my_i的值 - 清除? : - )

这是封闭的奇妙世界。首先得到它可能需要一点精神上的弯曲,但是你会很高兴你这样做,所以去谷歌“javascript关闭”致死!

答案 2 :(得分:2)

这可能是Russ Cam答案的一个更明显的变体:

function Controls() {
  var Controls = document.getElementById("Quote_App").getElementsByTagName("dd");

  var createHandlerFor = function(CurrentControl) {
    return function() {
      var lorem=new Lorem(CurrentControl);
      lorem.Control=CurrentControl;
      alert(lorem.Amet());
    }
  };

  for (var i=0; i<Controls.length; i++) {
    Event("add", createHandlerFor(Controls[i]), "click", Controls[i]);
  }
};