JavaScript 循环问题与变量范围

发布于 2024-11-15 20:15:32 字数 3705 浏览 2 评论 0原文

所以,我有这个 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/

在循环结束时,任何 xmylist[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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

呢古 2024-11-22 20:15:32

问题是每个pin.XYZ都是相同对象——即Pushpin.prototype.XYZ

简单的“修复”是使用:

var pin = new Pushpin(...)
pin.XYZ = {
   site: item
   // the following will get tedious fast, consider one of the "property copy"
   // implementations floating about -- including jQuery.extend   
   getHtmlDescription: Pushpin.prototype.XYZ.getHtmlDescription
}

它将为每个新图钉对象的 XYZ 属性分配一个对象。当然,这也可以进行不同的设计:)

至少,将 XYZ 移出 Pushpin.prototype 对象——这将允许它被很好地视为一个对象(就像 >this 的传递实际上使得悬挂在原型对象上的函数几乎不可能访问原型所应用的对象的实例数据);最终代码可能类似于:

// We .. "wrap" the real Pushpin constructor
// somewhere global after Bing Mapi JS loaded
Pushpin = (function (bingPushpin) {
   return function Pushpin (...) {
       var pin = new bingPushpin(...)
       pin.XYZ = new XYZ()
       // trick of "returning" from ctor
       return pin
   }
})(PushPin)
// ...
var pin = new Pushpin(...)
pin.XYZ.site = item

快乐编码。


更新前的答案:

这实际上不是一个范围问题——没有创建无意的闭包,并且每个表达式都经过严格评估。

我怀疑还有另一个问题,例如意外的输入(数据包含一堆相同的项目)或有缺陷的假设(例如对象被神奇地克隆)或不相关的东西。

快乐编码。


分析:

 var mylist = [];
 $.each(data, function (i, item) {
     // creates new object
     var pin = new Pushpin(x, y);
     // property of new object assigned
     // remember that no "duplication" is occurring
     pin.site = item;
     // new object pushed to array
     mylist.push(pin);
 });

因此,pin 不会是相同的,但 item 每个循环可能会计算出相同的对象。 (唯一的例外是 Pushpin 构造函数使用 return 返回一个现有对象,这确实是一个有趣的事情。)

The issue is that each pin.XYZ is the same object -- namely Pushpin.prototype.XYZ.

The simple "fix" is to use:

var pin = new Pushpin(...)
pin.XYZ = {
   site: item
   // the following will get tedious fast, consider one of the "property copy"
   // implementations floating about -- including jQuery.extend   
   getHtmlDescription: Pushpin.prototype.XYZ.getHtmlDescription
}

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 that this 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:

// We .. "wrap" the real Pushpin constructor
// somewhere global after Bing Mapi JS loaded
Pushpin = (function (bingPushpin) {
   return function Pushpin (...) {
       var pin = new bingPushpin(...)
       pin.XYZ = new XYZ()
       // trick of "returning" from ctor
       return pin
   }
})(PushPin)
// ...
var pin = new Pushpin(...)
pin.XYZ.site = item

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:

 var mylist = [];
 $.each(data, function (i, item) {
     // creates new object
     var pin = new Pushpin(x, y);
     // property of new object assigned
     // remember that no "duplication" is occurring
     pin.site = item;
     // new object pushed to array
     mylist.push(pin);
 });

Therefor, no pin will be the same but it is possible that item evaluates to the same object each loop. (The only exception to this is if the Pushpin constructor uses return to return an existing object, which would be a fun fine indeed.)

热情消退 2024-11-22 20:15:32

考虑到你在一个函数中,我会说是的,当然它们都指向同一个对象,因为你只是通过引用传递。环顾四周后,我偶然发现了这个 - 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?

假面具 2024-11-22 20:15:32

阅读 MoarCodePlz 的答案后,我想这可能有助于解决“通过引用”问题。不过还没有验证过。

 var mylist = [];
 $.each(data, function (i, item) {
     // Creates the new object as a part of yourlist
     mylist.push(new Pushpin(x, y));
     // property of new object assigned item
     mylist[x].site = item;
 });

After reading MoarCodePlz's answer I thought maybe this could help getting around the 'by reference' issue. Haven't verified it though.

 var mylist = [];
 $.each(data, function (i, item) {
     // Creates the new object as a part of yourlist
     mylist.push(new Pushpin(x, y));
     // property of new object assigned item
     mylist[x].site = item;
 });
半衾梦 2024-11-22 20:15:32

您需要在 .each 之外声明 var pin 吗?
然后在 .each 中将其设置为 new。

var pin;
 var mylist = [];
 $.each(data, function (i, item) {
     try {
         pin = new Pushpin(x, y);
         pin.site = item;
         mylist.push(pin);
     } catch (e) { alert (e); }
 });

Do you need to declare the var pin outside of the .each?
then set it to new inside the .each.

var pin;
 var mylist = [];
 $.each(data, function (i, item) {
     try {
         pin = new Pushpin(x, y);
         pin.site = item;
         mylist.push(pin);
     } catch (e) { alert (e); }
 });
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文