Javascript - 使用for...in遍历对象时出现问题

3

我有一个动态生成的对象,看起来像这样:

colorArray = { 
    AR: "#8BBDE1", 
    AU: "#135D9E", 
    AT: "#8BBDE1",
    ... }

我正在尝试使用这个插件,并在调用插件时使用“colors”属性来为地图着色。代码如下:

$('#iniDensityMap').vectorMap({
    backgroundColor: '#c2e2f2',
    colors: colorArray,
    ... (some other params)
});

但是这并不会着色国家。当我在代码中硬编码时,它可以正常工作,但是对于这个项目必须是动态生成的,所以像这样的代码对我来说行不通(尽管实际上可以着色地图):

$('#iniDensityMap').vectorMap({
    backgroundColor: '#c2e2f2',
    colors: { AR: "#8BBDE1", AU: "#135D9E", AT: "#8BBDE1" },
    ... (some other params)
});

我已经追踪了这个插件的问题,发现它与以下循环有关:

setColors: function(key, color) {
  if (typeof key == 'string') {
    this.countries[key].setFill(color);
  } else {

    var colors = key; //This is the parameter passed through to the plugin

    for (var code in colors) {

      //THIS WILL NOT GET CALLED

      if (this.countries[code]) {
        this.countries[code].setFill(colors[code]);
      }
    }
  }
},

我也尝试了在插件之外遍历colorArray对象,但是我遇到了同样的问题。 无论放在for ( var x in obj )里的任何内容都没有执行。我还注意到colorArray.length返回未定义。 另一个重要的注意事项是,我已经在另一个调用中实例化了var colorArray = {};,试图确保它位于全局范围内,并且能够被操作。
我认为问题可能是:
  1. 我动态填充对象的方式 - colorArray[cCode] = cColor;(在jQuery .each调用中)
  2. 我再次混淆了JavaScript中Arrays()和Objects()之间的区别
  3. 这可能是作用域问题?
  4. 以上所有因素的某种组合。
编辑#1:我已将有关Firebug控制台中对象的附加问题移动到此处的新帖子中。 该问题更具体地涉及Firebug而不是我在这里询问的JS底层问题。 编辑#2:附加信息 以下是我用于动态填充对象的代码:
function parseDensityMapXML() {
$.ajax({
    type: "GET",
    url: "media/XML/mapCountryData.xml",
    dataType: "xml",
    success: function (xml) {
        $(xml).find("Country").each(function () {
            var cName = $(this).find("Name").text();
            var cIniCount = $(this).find("InitiativeCount").text();
            var cUrl = $(this).find("SearchURL").text();
            var cCode = $(this).find("CountryCode").text();

            //Populate the JS Object
            iniDensityData[cCode] = { "initiatives": cIniCount, "url": cUrl, "name": cName };
            //set colors according to values of initiatives count
            colorArray[cCode] = getCountryColor(cIniCount);
        });
    }
});
} //end function parseDensityMapXML();

然后,此函数会在页面其他地方的复选框的点击事件上调用。对象iniDensityDatacolorArray在html文件头部声明 - 希望这样可以将它们保留在全局范围内:

<script type="text/javascript">
    //Initialize a bunch of variables in the global scope
    iniDensityData = {};
    colorArray = {};
</script>

最后,这是正在被读取的XML文件中的一段代码片段:
<?xml version="1.0" encoding="utf-8"?>
<icapCountryData>
  <Country>
    <Name>Albania</Name>
    <CountryCode>AL</CountryCode>
    <InitiativeCount>7</InitiativeCount>
    <SearchURL>~/advance_search.aspx?search=6</SearchURL>
  </Country>
  <Country>
    <Name>Argentina</Name>
    <CountryCode>AR</CountryCode>
    <InitiativeCount>15</InitiativeCount>
    <SearchURL>~/advance_search.aspx?search=11</SearchURL>
  </Country>
  ... and so on ...
</icapCountryData>

还有,当您在for循环上设置断点时,colors的值是否符合您的预期? - Dan Davies Brackett
@DanDaviesBrackett 是的,我很确定我想要使用{}(对象,对吗?)而不是.length,但肯定for/in循环可以用吧? - Tim
@HerroRygar 我很确定这是正确的,在jQuery ajax调用的成功回调函数中,我正在执行以下操作: $(xml).find("Country").each(function () { var cCode = $(this).find("CountryCode").text(); ...一些其他的东西 } 然后像这样填充colorArraycolorArray[cCode] = cColor; - Tim
但是,如果您可以发布有问题的整个代码块,那将更容易诊断作用域问题。 - rybosome
你可能不应该把一个 Object 称作 Array。在 JavaScript 中,数组使用方括号表示 var arr = [];。如果称其为数组,会让我们认为你很困惑... - ErikE
显示剩余3条评论
1个回答

3
解决了! 最初,我调用了函数parseDensityMapXML(),然后立即调用另一个函数loadDensityMapXML(),该函数使用在第一个函数中动态创建的对象进行迭代。问题是,它没有作为第一个函数的回调函数被调用,因此在对象甚至还没有构建完成时就开始执行了。
为了解决这个问题,我只需修改上述第一个函数,在.each()完成对象创建之后调用第二个函数即可:after
function parseDensityMapXML() {
$.ajax({
    type: "GET",
    url: "media/XML/mapCountryData.xml",
    dataType: "xml",
    success: function (xml) {
        $(xml).find("Country").each(function () {
            var cName = $(this).find("Name").text();
            var cIniCount = $(this).find("InitiativeCount").text();
            var cUrl = $(this).find("SearchURL").text();
            var cCode = $(this).find("CountryCode").text();

            //Populate the JS Object
            iniDensityData[cCode] = { "initiatives": cIniCount, "url": cUrl, "name": cName };
            //set colors according to values of initiatives count
            colorArray[cCode] = getCountryColor(cIniCount);
        });

        /* and then call the jVectorMap plugin - this MUST be done as a callback
           after the above parsing.  If called separately, it will fire before the
           objects iniDensityData and colorArray are created! */
        loadDensityMapXML();
    }
});
} //end function parseDensityMapXML();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接