了解javascript列表适配器中的作用域
我正在动态创建了解javascript列表适配器中的作用域,javascript,jquery,html,scope,Javascript,Jquery,Html,Scope,我正在动态创建按钮列表,并将它们附加到span中。每个按钮都与通过ajax下载的JSON数据相关联。数据显然在工作,但是我的jQuery单击事件没有获得正确的索引数据。也就是说,应该与该单元格关联的数据不是-我单击的任何单元格实际上都只对应于列表中最后一个元素的数据。更清楚地说,以下是我拥有的(或可用的小提琴): JSON数据 var data = [{"id":0, "name":"Phil"}, {"id":1, "name":"Ed"}, {"id":2, "name":"Fred"}]
按钮列表
,并将它们附加到span
中。每个按钮都与通过ajax下载的JSON数据相关联。数据显然在工作,但是我的jQuery
单击事件没有获得正确的索引数据。也就是说,应该与该单元格关联的数据不是-我单击的任何单元格实际上都只对应于列表中最后一个元素的数据。更清楚地说,以下是我拥有的(或可用的小提琴):
- JSON数据
var data = [{"id":0, "name":"Phil"}, {"id":1, "name":"Ed"}, {"id":2, "name":"Fred"}];
- HTML文件
<span id="output"></span><br>
- 代码
for (var i = 0; i < data.length; i++) {
var person = data[i];
var button = document.createElement('button');
button.type = 'button';
$(button).addClass('listButton');
var text = "<b>ID:</b> " + person.id + "<br>";
text = text + "<b>Name:</b> " + person.name;
$(button).html(text);
$(button).click(function() {
alert("selected person: " + person.id);//always 2, no matter who is clicked.
});
document.getElementById("output").appendChild(button);
}
for(变量i=0;i”;
text=text+“Name:”+person.Name;
$(按钮).html(文本);
$(按钮)。单击(函数(){
警报(“所选人员:+person.id);//始终为2,无论单击的是谁。
});
document.getElementById(“输出”).appendChild(按钮);
}
- 结果
(单击任意单元格以查看警报“所选人员:2”)
我的第一个想法是这是一个范围问题——这意味着每次我创建一个新按钮时,它都在为其他每个单元格更新按钮。我的第一次修复尝试是在主for循环中设置jQuery数据:$(button.data(“id”,person.id)代码>,然后将其返回到单击函数中:$(按钮)。数据(“id”)
。不用说,这是行不通的
我做错了什么,如何修复它?这就是JavaScript中作用域的工作原理。像if
这样的条件和像for
这样的循环没有作用域,除了深奥的情况外,只有函数作用域
这个问题在初学者中很常见
您没有循环作用域,您的警报绑定到人
,循环结束时是第三个人
如果希望每个处理程序对相应的人做出反应,则需要“关闭”事件处理程序中的人
(function(person){
$(button).click(function() {
alert("selected person: " + person.id);//correct value!
});
})(person); // close over the person
我们正在创建一个包装处理程序的函数,它跟踪传递给它的person
的值,以便处理程序知道在什么值上运行
另一种方法是使用,它将对数组中的每个人运行一个函数,有效地创建范围
这将类似于:
data.forEach(function(person){
var button = document.createElement('button');
button.type = 'button';
$(button).addClass('listButton');
var text = "<b>ID:</b> " + person.id + "<br>";
text = text + "<b>Name:</b> " + person.name;
$(button).html(text);
$(button).click(function() {
alert("selected person: " + person.id);
});
document.getElementById("output").appendChild(button);
});
HTML:
ID:
姓名:
这就是JavaScript中作用域的工作原理。像if
这样的条件和像for
这样的循环没有作用域,除了深奥的情况外,只有函数作用域
这个问题在初学者中很常见
您没有循环作用域,您的警报绑定到人
,循环结束时是第三个人
如果希望每个处理程序对相应的人做出反应,则需要“关闭”事件处理程序中的人
(function(person){
$(button).click(function() {
alert("selected person: " + person.id);//correct value!
});
})(person); // close over the person
我们正在创建一个包装处理程序的函数,它跟踪传递给它的person
的值,以便处理程序知道在什么值上运行
另一种方法是使用,它将对数组中的每个人运行一个函数,有效地创建范围
这将类似于:
data.forEach(function(person){
var button = document.createElement('button');
button.type = 'button';
$(button).addClass('listButton');
var text = "<b>ID:</b> " + person.id + "<br>";
text = text + "<b>Name:</b> " + person.name;
$(button).html(text);
$(button).click(function() {
alert("selected person: " + person.id);
});
document.getElementById("output").appendChild(button);
});
HTML:
ID:
姓名:
当您编写以下内容时:
function() {
for (var i = 0; i < 10; i++) {
var k = i;
}
}
function() {
var k, i;
for (i=0; i<10; i++) {
k=i;
}
}
当你写这篇文章时:
function() {
for (var i = 0; i < 10; i++) {
var k = i;
}
}
function() {
var k, i;
for (i=0; i<10; i++) {
k=i;
}
}
但这里的问题并不是提升,而是在标准循环/条件构造中没有块作用域。答案似乎是正确的。@BenjaminGruenbaum:正确。删除了那行-我需要停止多任务。谢谢你的解释-这真的很有帮助!但这里的问题并不是提升,而是在标准循环/条件构造中没有块作用域。答案似乎是正确的。@BenjaminGruenbaum:正确。删除了那行-我需要停止多任务。谢谢你的解释-这真的很有帮助!下面是一个使用.data()
:)@Bondye的工作示例。data
是一种可怕的破坏性方法,违反了关注点分离。您将DOM作为知识的来源,而不是JavaScript对象和JSON数据。请参阅我回答中的“我将如何做”部分。下面是一个使用.data()
:)@Bondye的工作示例。data
是一种可怕的破坏性方法,违反了关注点分离。您将DOM作为知识的来源,而不是JavaScript对象和JSON数据。请看我回答中的“我将如何做”部分。这是一个很好的回答-它涉及到我做错了什么,我如何修复它,甚至进一步解释了我如何从整体上改进代码。谢谢你的详尽回答@Phil不客气,请考虑删除,它只是处理数据绑定,让你专注于重要的事情,编写HTML一样的HTML,JavaScript,如JavaScript,并告诉它什么是绑定到什么。这是一个非常好的资源:)好运气这是一个很好的回答-它涉及到我做错了什么,我如何修复它,甚至进一步解释了我如何从整体上改进代码。谢谢你的详尽回答@Phil不客气,请考虑删除,它只是处理数据绑定,让你专注于重要的事情,编写HTML一样的HTML,JavaScript,如JavaScript,并告诉它什么是绑定到什么。这是一个非常好的资源:)祝你好运
for (var i = 0; i < data.length; i++) {
(function(person) {
var button = document.createElement('button');
button.type = 'button';
$(button).addClass('listButton');
var text = "<b>ID:</b> " + person.id + "<br>";
text = text + "<b>Name:</b> " + person.name;
$(button).html(text);
$(button).click(function() {
alert("selected person: " + person.id);//always 2, no matter who is clicked.
});
document.getElementById("output").appendChild(button);
})(data[i]);
}