为什么只在Javascript中为onClick填充数组的最后一个元素

时间:2013-03-12 17:30:14

标签: javascript

我循环遍历一个对象数组,我遇到了奇怪的行为。这是我的代码:

  window.onload = function () {

    document.getElementById('btnAdd').onclick = function () {
        add("button");
    };
    function add(type) {
        var names = {};
        names['one'] = { id: "Button 1",msg:"#1" };
        names['two'] = { id: "Button 2", msg: "#2" };
        names['three'] = { id: "Button 3", msg: "#3" };
        //Create an input type dynamically.
        function addOnClick(element, currentName) {
              element.onClick = function () {
                 alert("button is " + names[currentName].msg);
            };
          };       

        for (name in names) {
            var element = document.createElement("input");

            element.type = type;
            element.value = names[name].id; 
            element.name = name;  
             addOnClick(element,name);

            var foo = document.getElementById("fooBar");
            //Append the element in page (in span).  
            foo.appendChild(element);
        }
    }
};

继承人html:

 <p>
<input type="button" id="btnAdd" value="Add Buttons" />
<p id="fooBar">Buttons:   </p>

</p>

如果您在浏览器中运行此功能,并在“添加按钮”按钮中创建3个按钮并进行相应命名。但是如果你点击3个新按钮中的一个,警告框总是说“按钮是#3”,我不明白为什么。有人可以解释为什么onClick事件只记住我的数组中的最后一项?感谢

3 个答案:

答案 0 :(得分:3)

你正在成为javascript中关闭捕获规则的牺牲品。只有name的一个副本,当onclick触发时,它将是集合name中的最后一个names值。为了解决这个问题,您需要创建一个新的function范围来捕获name的当前值

var addOnClick = function(currentName) { 
  element.onclick = function() { 
    alert("button is " + names[currentName].msg);
  };
};
addOnClick(name);

修改

您还需要使用onclick而不是onClick。案件在这里很重要

  

小提琴:http://jsfiddle.net/Nzf3p/

答案 1 :(得分:2)

这是由于闭包在Javascript(捕获局部变量)中的工作方式。分配给element.onclick的匿名函数是:

function () { 
    // Note this is a function
    alert("button is "+ names[name].msg);
};

这里,name的值绑定到循环中遇到的最后一个值,这是最后一个元素。循环中基本上name指向外部循环中name使用的内存位置。该位置不断更新,最后指向值three。要解决这个问题,您需要一个额外的函数(创建一个新的范围)来保留name的值。这将创建一个name版本,该版本对于该新函数是本地的,因此会保留:

//A self-invoked function, into which you pass name. preservedName is the preserved
//value of name, which is local to the scope of this self-invoked function.
(function(preservedName) {
    element.onclick = function() {
        alert("button is " + names[preservedName].msg);
    };
})(name);

答案 2 :(得分:1)

问题是由于您为onclick处理程序创建的闭包。

element.onclick = function () { // Note this is a function
            alert("button is "+ names[name].msg);
        };

应该包含一个传递您感兴趣的名称的函数:

addOnClickToElement(element,name);

然后在与“add”相同的范围内添加此命名函数,以便可以访问names

function addOnClickToElement(element,name) { // Note this is a function
    element.onclick = function(){alert("button is "+ names[name].msg);};
}