Google Chrome:JavaScript关联数组,按顺序进行评估

时间:2009-03-12 22:29:00

标签: javascript google-chrome associative-array

好的,所以在网页上,我有一个JavaScript对象,我将其用作关联数组。当页面加载时,这在脚本块中静态存在:

var salesWeeks = {
    "200911" : ["11 / 2009", "Fiscal 2009"],
    "200910" : ["10 / 2009", "Fiscal 2009"],
    "200909" : ["09 / 2009", "Fiscal 2009"],
    "200908" : ["08 / 2009", "Fiscal 2009"],
    "200907" : ["07 / 2009", "Fiscal 2009"],
    "200906" : ["06 / 2009", "Fiscal 2009"],
    "200905" : ["05 / 2009", "Fiscal 2009"],
    "200904" : ["04 / 2009", "Fiscal 2009"],
    "200903" : ["03 / 2009", "Fiscal 2009"],
    "200902" : ["02 / 2009", "Fiscal 2009"],
    "200901" : ["01 / 2009", "Fiscal 2009"],
    "200852" : ["52 / 2008", "Fiscal 2009"],
    "200851" : ["51 / 2008", "Fiscal 2009"]
};

键/值对的顺序是有意的,因为我将对象转换为HTML选择框,如下所示:

<select id="ddl_sw" name="ddl_sw">
<option value="">== SELECT WEEK ==</option>
<option value="200911">11 / 2009 (Fiscal 2009)</option>
<option value="200910">10 / 2009 (Fiscal 2009)</option>
<option value="200909">09 / 2009 (Fiscal 2009)</option>
<option value="200908">08 / 2009 (Fiscal 2009)</option>
<option value="200907">07 / 2009 (Fiscal 2009)</option>
<option value="200906">06 / 2009 (Fiscal 2009)</option>
<option value="200905">05 / 2009 (Fiscal 2009)</option>
<option value="200904">04 / 2009 (Fiscal 2009)</option>
<option value="200903">03 / 2009 (Fiscal 2009)</option>
<option value="200902">02 / 2009 (Fiscal 2009)</option>
<option value="200901">01 / 2009 (Fiscal 2009)</option>
<option value="200852">52 / 2008 (Fiscal 2009)</option>
<option value="200851">51 / 2008 (Fiscal 2009)</option>
</select>

...代码看起来像这样(从函数中剪断):

var arr = [];
arr.push(
    "<select id=\"ddl_sw\" name=\"ddl_sw\">" +
    "<option value=\"\">== SELECT WEEK ==</option>"
);

for(var key in salesWeeks)
{
    arr.push(
        "<option value=\"" + key + "\">" +
        salesWeeks[key][0] + " (" + salesWeeks[key][1] + ")" +
        "<\/option>"
    );
}

arr.push("<\/select>");

return arr.join("");

这一切在IE,FireFox和Opera中都能正常工作。

然而,在Chrome中,订单出乎意料:

<select id="ddl_sw" name="ddl_sw">
<option value="">== SELECT WEEK ==</option>
<option value="200852">52 / 2008 (Fiscal 2009)</option>
<option value="200908">08 / 2009 (Fiscal 2009)</option>
<option value="200906">06 / 2009 (Fiscal 2009)</option>
<option value="200902">02 / 2009 (Fiscal 2009)</option>
<option value="200907">07 / 2009 (Fiscal 2009)</option>
<option value="200904">04 / 2009 (Fiscal 2009)</option>
<option value="200909">09 / 2009 (Fiscal 2009)</option>
<option value="200903">03 / 2009 (Fiscal 2009)</option>
<option value="200905">05 / 2009 (Fiscal 2009)</option>
<option value="200901">01 / 2009 (Fiscal 2009)</option>
<option value="200910">10 / 2009 (Fiscal 2009)</option>
<option value="200911">11 / 2009 (Fiscal 2009)</option>
<option value="200851">51 / 2008 (Fiscal 2009)</option>
</select>

注意:此订单虽然很奇怪,但在后续刷新时不会改变。它始终按此顺序排列。

那么,Chrome正在做什么?如何处理循环?

首先,我错误地依赖于任何关联数组中声明键/值对的顺序?

我之前从未质疑它,我只是假设订单会持续,因为这种技术在其他浏览器中一直对我有效。但我想我从来没有看到它说明订单得到保证。也许不是吗?

任何见解都会很棒。 感谢。

7 个答案:

答案 0 :(得分:10)

将关联数组视为纸袋,所有键值对都放在纸袋中。当你把手伸进麻袋里看看对子时(比如for ... in循环),你遇到它们的顺序是出于所有实际目的而随机的。

如果要按特定顺序查看它们,则需要将密钥提取到数组中并对其进行排序。然后遍历数组,使用您遇到的键索引到关联数组。

答案 1 :(得分:8)

无法保证元素存储在关联数组中的顺序。您必须明确对输出进行排序。

答案 2 :(得分:2)

正如其他答案所说,对象的属性被迭代的顺序没有在规范中定义,即使主要的浏览器都按照定义的顺序迭代它们。

如果所有对象的属性都包含原始值,则Chrome也会按顺序枚举它们。 John Resig在此提供了有关Chrome的行为的更多详细信息(在“for循环顺序”下): http://ejohn.org/blog/javascript-in-chrome/

答案 3 :(得分:2)

正如所指出的,Chrome的行为完全有效。

这是一个很好的案例,一些OO思想可以帮助。你真的想要一个关联数组或只是一个对象列表吗?

var salesWeeks = [
    ["200911", "11 / 2009", "Fiscal 2009"],
    ...
]
...
for(var key in salesWeeks)
{
    arr.push(
        "<option value=\"" + salesWeeks[key][0] + "\">" +
        salesWeeks[key][1] + " (" + salesWeeks[key][2] + ")" +
        "<\/option>"
    );
}

我会更好地为你服务(对那些提倡某种形式排序的人来说,订单已经定义了 - 你为什么要做额外的工作?)

答案 4 :(得分:2)

@curtainDog:不!没有!在JavaScript中使用“for .. in”与Array对象是不好的 - 这里大多数响应的全部内容是“for ... in”不保证任何顺序。此外,“for ... in”将从对象的构造函数的原型中获取属性,并且不会迭代不存在的键。

@Samnan:规范只是说迭代顺序不能保证;这意味着浏览器可以按照排序顺序,按照随机顺序按插入顺序进行迭代,也可以随意进行迭代。它就像一个哈希表 - 将其视为随机的,即使它恰好以某种明显的顺序出现。

我很确定大多数浏览器都会使用Array对象查找“for..in”并按数字顺序迭代,这样就不会破坏;但是,大多数使用它的人并没有真正做到这一点,并且除非你特别需要 object -type迭代,否则应该避免使用它。

答案 5 :(得分:2)

这不是一个真正的好习惯,但是......

如果您为值添加空格,则chrome不会将值视为数字,也不会按值对其进行排序。

示例:

<select>
  <option value=" 3">Third</option>
  <option value=" 1">First</option>
  <option value=" 2">Second</option>
</select>

好的一面是你不必像有人建议的那样添加然后从ID中删除字母字符(不记得是否在这个或其他有类似问题的帖子中),你可以很容易地修剪它但是大多数时候空间被忽略,如果你发布或将它们发送到另一个文件,他们只会看到整数值而不是空格。

答案 6 :(得分:-3)

与所有其他答案相反,它只是一个小小的错误

原因:

如果数据结构是像Barry那样的纸袋,那么:

值应始终保持不变。这不是chrome中的情况

如果数据结构是顺序的,那么:

值应按照将它们添加到结构中的顺序

虽然其他浏览器遵循第二种方法,但chrome并未遵循,并且仍然没有解释在访问数据结构时chrome如何排序数据结构。