我循环遍历一个对象数组,我遇到了奇怪的行为。这是我的代码:
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事件只记住我的数组中的最后一项?感谢
答案 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
。案件在这里很重要
答案 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);};
}