1

我正在遍历一系列对象,并且遇到了奇怪的行为。这是我的代码:

  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 事件只记住我数组中的最后一项吗?谢谢

4

3 回答 3

4

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

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

编辑

您还需要使用onclicknot onClick。案件在这里很重要

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

于 2013-03-12T17:34:05.363 回答
2

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

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

这里, 的值name绑定到循环中遇到的最后一个值,即最后一个元素。本质name上,在循环中指向name外部循环中使用的内存位置。该位置不断更新,最后指向 value 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);
于 2013-03-12T17:35:45.977 回答
1

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

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

应该由传入您感兴趣的名称的函数包装:

addOnClickToElement(element,name);

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

function addOnClickToElement(element,name) { // Note this is a function
    element.onclick = function(){alert("button is "+ names[name].msg);};
}
于 2013-03-12T17:37:42.877 回答