7

好的,所以在网页上,我有一个 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 在做什么呢?它如何处理循环的一些优化?

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

我以前从未质疑过它,我只是假设这个顺序会成立,因为这种技术在其他浏览器中一直对我有用。但我想我从未见过它在任何地方都说订单是有保证的。也许不是?

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

4

7 回答 7

10

将关联数组想象成一个纸袋,其中放置了所有键值对。当您将手伸入麻袋查看这些对时(例如使用 for...in 循环),您遇到它们的顺序实际上是随机的。

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

于 2009-03-12T22:42:03.503 回答
8

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

于 2009-03-12T22:33:41.467 回答
2

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

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

于 2009-03-12T23:10:06.277 回答
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>"
    );
}

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

于 2010-05-24T22:20:17.050 回答
2

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

@Samnan:规范只是说不能保证迭代顺序;这意味着浏览器可以自由地以排序顺序、插入顺序、随机顺序或其他方式进行迭代。它就像一个哈希表——认为它是随机的,即使它碰巧以某种明显的顺序出现。

我相当确定大多数浏览器会使用 Array 对象查找“for..in”,并按数字顺序进行迭代,这样事情就不会中断;然而,它并没有像大多数使用它的人认为的那样做,除非你特别需要object类型的迭代,否则应该避免它。

于 2011-01-23T22:00:14.250 回答
2

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

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

例子:

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

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

于 2012-07-05T22:08:03.197 回答
-3

与所有其他答案相反,它肯定是 Chrome 中的一个错误

原因:

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

值应始终随机化。铬不是这种情况

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

这些值应按它们添加到结构中的顺序排列

虽然其他浏览器遵循第二种方法,但 chrome 都不遵循,并且仍然没有解释 chrome 在访问时对数据结构的排序顺序是什么。

于 2010-09-29T13:44:17.653 回答