JavaScript 循环问题与变量范围
所以,我有这个 jQuery .each
循环,并且在很大程度上它按预期工作;有一个问题,但首先是循环:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.6.1.min.js"></script>
<script type="text/javascript">
function Pushpin(){}
Pushpin.prototype.XZX = {
site: null,
getHtmlDescription: function () {
var html = '<b id="infoboxTitle" style="position:absolute; top:10px; left:10px; width:220px;">' + this.site.Name + '</b>';
html += '<a id="infoboxDescription" style="position:absolute; top:30px; left:10px; width:220px; height:120px;">{0}</a>';
var description = 'Headcount: ' + this.site.Headcount + '<br />';
description += 'Leases: ' + this.site.LeaseCount + '<br />';
html = html.replace('{0}', description);
return html;
}
};
var data = [
{"Address":{"City":"Atlanta","Country":"USA","County":"","Latitude":33.9882404987503,"Longitude":-84.1629638209203,"Region":"Southeast","State":"GA","StreetAddress":"Atlanta 177","ZipCode":"30096"},"Headcount":0,"ImageBytes":null,"ImageRefPath":"","LeaseCount":1,"Leases":null,"Name":"Atlanta","NextExpire":"\/Date(1495083600000-0500)\/","Number":"1052","PrimaryUse":"Garage","PropertyID":"OMNI","RecID":32839,"RecordID":1004,"RentableSquareFootage":22000,"SiteRecordID":"DEMO_29626","SiteTotalDollars":0,"Status":null,"Type":"LSE"},
{"Address":{"City":"Bellevue","Country":"USA","County":"","Latitude":47.6043250620083,"Longitude":-122.14236047437,"Region":"Northwest","State":"WA","StreetAddress":"Seattle 51","ZipCode":"98007"},"Headcount":0,"ImageBytes":null,"ImageRefPath":"","LeaseCount":1,"Leases":null,"Name":"Bellevue","NextExpire":"\/Date(1260424800000-0600)\/","Number":"1078","PrimaryUse":"Tower","PropertyID":"OMNI","RecID":32865,"RecordID":1027,"RentableSquareFootage":7652,"SiteRecordID":"DEMO_275651","SiteTotalDollars":0,"Status":null,"Type":"LSE"}
];
var mylist = [];
$.each(data, function (i, item) {
try {
var pin = new Pushpin();
pin.XZX.site = item;
mylist.push(pin);
} catch (e) { alert (e); }
});
$(document).ready(function() {
$('#btnAlert').click(function () {
$('#content').html(mylist[$('#index').val()].XZX.getHtmlDescription());
} );
});
</script>
</head>
<body >
<div style="margin-left:auto; margin-right:auto; width:300px;">
<div style="position:relative; width:250px;">
<select id="index">
<option>0</option>
<option>1</option>
</select>
<input type="submit" id="btnAlert"/>
</div>
<div id="content" style="position:relative;width:250px;"></div>
</div>
</body>
</html>
也可在 jsfiddle 上使用: http://jsfiddle.net/M8YS2/
在循环结束时,任何 x
的 mylist[x].site
都指向我的数据项的同一个实例,我该如何解决这个问题?
So, I have this jQuery .each
loop, and for the most part its working as intended; there is one issue, but first the loop:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.6.1.min.js"></script>
<script type="text/javascript">
function Pushpin(){}
Pushpin.prototype.XZX = {
site: null,
getHtmlDescription: function () {
var html = '<b id="infoboxTitle" style="position:absolute; top:10px; left:10px; width:220px;">' + this.site.Name + '</b>';
html += '<a id="infoboxDescription" style="position:absolute; top:30px; left:10px; width:220px; height:120px;">{0}</a>';
var description = 'Headcount: ' + this.site.Headcount + '<br />';
description += 'Leases: ' + this.site.LeaseCount + '<br />';
html = html.replace('{0}', description);
return html;
}
};
var data = [
{"Address":{"City":"Atlanta","Country":"USA","County":"","Latitude":33.9882404987503,"Longitude":-84.1629638209203,"Region":"Southeast","State":"GA","StreetAddress":"Atlanta 177","ZipCode":"30096"},"Headcount":0,"ImageBytes":null,"ImageRefPath":"","LeaseCount":1,"Leases":null,"Name":"Atlanta","NextExpire":"\/Date(1495083600000-0500)\/","Number":"1052","PrimaryUse":"Garage","PropertyID":"OMNI","RecID":32839,"RecordID":1004,"RentableSquareFootage":22000,"SiteRecordID":"DEMO_29626","SiteTotalDollars":0,"Status":null,"Type":"LSE"},
{"Address":{"City":"Bellevue","Country":"USA","County":"","Latitude":47.6043250620083,"Longitude":-122.14236047437,"Region":"Northwest","State":"WA","StreetAddress":"Seattle 51","ZipCode":"98007"},"Headcount":0,"ImageBytes":null,"ImageRefPath":"","LeaseCount":1,"Leases":null,"Name":"Bellevue","NextExpire":"\/Date(1260424800000-0600)\/","Number":"1078","PrimaryUse":"Tower","PropertyID":"OMNI","RecID":32865,"RecordID":1027,"RentableSquareFootage":7652,"SiteRecordID":"DEMO_275651","SiteTotalDollars":0,"Status":null,"Type":"LSE"}
];
var mylist = [];
$.each(data, function (i, item) {
try {
var pin = new Pushpin();
pin.XZX.site = item;
mylist.push(pin);
} catch (e) { alert (e); }
});
$(document).ready(function() {
$('#btnAlert').click(function () {
$('#content').html(mylist[$('#index').val()].XZX.getHtmlDescription());
} );
});
</script>
</head>
<body >
<div style="margin-left:auto; margin-right:auto; width:300px;">
<div style="position:relative; width:250px;">
<select id="index">
<option>0</option>
<option>1</option>
</select>
<input type="submit" id="btnAlert"/>
</div>
<div id="content" style="position:relative;width:250px;"></div>
</div>
</body>
</html>
Also available on jsfiddle: http://jsfiddle.net/M8YS2/
At the end of the loop, mylist[x].site
for any x
all point to the same instance of my data item, how can I get around this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
问题是每个
pin.XYZ
都是相同对象——即Pushpin.prototype.XYZ
。简单的“修复”是使用:
它将为每个新图钉对象的
XYZ
属性分配一个新对象。当然,这也可以进行不同的设计:)至少,将
XYZ
移出 Pushpin.prototype 对象——这将允许它被很好地视为一个对象(就像>this
的传递实际上使得悬挂在原型对象上的函数几乎不可能访问原型所应用的对象的实例数据);最终代码可能类似于:快乐编码。
更新前的答案:
这实际上不是一个范围问题——没有创建无意的闭包,并且每个表达式都经过严格评估。
我怀疑还有另一个问题,例如意外的输入(数据包含一堆相同的项目)或有缺陷的假设(例如对象被神奇地克隆)或不相关的东西。
快乐编码。
分析:
因此,
pin
不会是相同的,但item
每个循环可能会计算出相同的对象。 (唯一的例外是 Pushpin 构造函数使用return
返回一个现有对象,这确实是一个有趣的事情。)The issue is that each
pin.XYZ
is the same object -- namelyPushpin.prototype.XYZ
.The simple "fix" is to use:
Which will assign a new object to the
XYZ
property of each new Pushpin object. Of course, this could be designed differently as well :)At the very least, move
XYZ
off the Pushpin.prototype object -- this will allow it to treated nicely as an object (the way thatthis
is passed about actually makes it nigh-impossible for a function dangling off an object of a prototype to access instance data of the object to which the prototype applies); the end-code might look something like:Happy coding.
Pre-update answer:
This actually isn't a scoping issue -- there are no inadvertent closures created and each expression is strictly evaluated.
I suspect there is another problem, such as unexpected input (data contains a bunch of the same item) or flawed assumption (such that objects are magically cloned) or something unrelated.
Happy coding.
Analysis:
Therefor, no
pin
will be the same but it is possible thatitem
evaluates to the same object each loop. (The only exception to this is if the Pushpin constructor usesreturn
to return an existing object, which would be a fun fine indeed.)考虑到你在一个函数中,我会说是的,当然它们都指向同一个对象,因为你只是通过引用传递。环顾四周后,我偶然发现了这个 - http://my.opera.com/GreyWyvern /blog/show.dml/1725165 - 但看起来没有用于克隆 Javascript 对象的直接选项。
也许您最好的方法是编写一个函数来克隆输入对象并将其作为新实例返回?
Considering you're within a function I would say yes of course they all point to the same object as you're only passing by reference. After looking around I stumbled upon this - http://my.opera.com/GreyWyvern/blog/show.dml/1725165 - but it doesn't look like there is a straight-forward option for cloning a Javascript object.
Perhaps your best approach would be to write a function that clones an input object and returns it as a new instance?
阅读 MoarCodePlz 的答案后,我想这可能有助于解决“通过引用”问题。不过还没有验证过。
After reading MoarCodePlz's answer I thought maybe this could help getting around the 'by reference' issue. Haven't verified it though.
您需要在 .each 之外声明 var pin 吗?
然后在 .each 中将其设置为 new。
Do you need to declare the var pin outside of the .each?
then set it to new inside the .each.