如何在JavaScript中通过索引引用数组项?

3

我有一个JavaScript数组:

Fruit > Banana > Colour > Yellow
               > Size   > Large
               > Cost   > $3.50
      > Apple  > Colour > Green
               > Size   > Small
               > Cost   > $0.42

我可以使用以下方法获取值:

alert(Fruit['Banana']['Colour']);

如何使用索引获取相同的值?例如:

alert(Fruit[0][0]);

感谢大家为我指引正确的方向,这是我需要的解决方案:

for (var a in Fruit) {
    //var a gives me "Banana" and "Apple"
    for (var b in Fruit[a]){
        //var b gives me "Colour", "Size" and "Cost"
        //Fruit[a][b] gives me the values
    }
}

1
你正在寻找一个关联数组吗? - fncomp
我看到你正在使用一个对象,但是想要同时使用索引。正如@Edgar Villegas Alvarado所提到的,这不是一种本地特性。 - fncomp
4个回答

4
看起来你把JavaScript 数组对象 和所有对象都是关联数组混淆了。请注意,普通对象(比如你提到的“Fruit”对象)没有固定的属性(键)排序,而数组对象有(由于整数索引的自然排序)。本质上,一个数组只是一个带有特殊“length”属性的对象,该属性存储最后一个整数索引(从零开始)加一。
任何对象的属性将以任意(例如随机)顺序迭代:
var obj = {a:'Aye', b:'Bee', c:'See', d:'Dee'};
for (var prop in obj) {
  alert(prop + '=' + obj[prop]); // No order is guaranteed.
}

严格来说,甚至数组也不能保证使用for-in循环按自然顺序迭代;但是,大多数JavaScript解释器仍然这样做。(值得注意的是,IE8按分配索引的顺序迭代,而不是按自然顺序。)这就是为什么你应该始终使用纯粹的“for”循环通过索引迭代数组的原因。
var arr = ['a', 'b', 'c', 'd', 'e', 'f'];
for (var i=0; i<arr.length; i++) { // i = [0 .. length-1]
  alert(arr + '=' + arr[i]); // Explicitly order as 'a', 'b', 'c'...
}

这些差异意味着,无论你如何定义你的“Fruit”对象,都没有可靠的方法来确保键的严格排序(例如,“Banana”,“Apple”,“Color”,“Size”等),除非你单独保留自己的排序。

好的,这很好,我可以获取“颜色”,“尺寸”和“成本”,那么我如何获取它们的值呢?像一个嵌套的for循环之类的吗? - Craig
@Craig:请看我的更新答案:尝试在for...in循环中使用obj[prop],其中prop是迭代变量。 - maerics
@maerics - 数组的属性(无论是数值还是其他类型)也没有顺序。数组只是具有特殊length属性的对象。 - RobG
@RobG:是的,关于Array对象是正确的,ECMA-262第5版规范指出枚举属性的顺序未指定;然而,在我使用过的每个JavaScript解释器中,数组将按顺序在for-in循环中迭代。 - maerics
@maerics 在 IE 中添加数组属性时,可以使用 for..in 循环。它们按照添加的顺序返回,而不是按数字排序(至少在 IE < 9 中)。 - RobG
@RobG:哇,刚在IE8上测试了一下,你说得完全正确。我会考虑如何以有用的方式更新我的答案... - maerics

3

我有点困惑,因为你似乎已经回答了自己的问题。我也不知道你的数组是如何设置的。但是如果你看一下这个例子,你就可以在这里看到它的工作原理:

http://jsfiddle.net/uyNnH/

这假设顶级数组包含您的水果类型,而第二级数组包含每个水果类型的属性。
更新:
来自Mozillaothers
在JavaScript 1.0中,您可以通过属性名称或序数索引来引用对象的属性。但是,在JavaScript 1.1或更高版本中,如果您最初通过名称定义属性,则必须始终按名称引用它,如果您最初通过索引定义属性,则必须始终按索引引用它。
因此,问题在于您声明了一个关联数组,而不是基于索引/序数的数组。我能想到的唯一解决方案是使用(丑陋的)for循环。以下是一些未经测试的伪代码:
function getItemByIndex(index, array) {
    var counter = 0;

    for (item in array)
    {
        if (counter == index)
        {
            return item;
        }

        counter++;
    }
}

我想要能够使用两种方法来获取值。然而,Fruit[0][0] 不起作用。 - Craig
我明白了...没有简单的方法可以做到...但我会修改我的答案。 - Kon
我猜数组看起来会像这样: Fruit = [香蕉 => [颜色 => '黄色',大小 => '大',成本 => '$3.50'],苹果=> [颜色 => '绿色',大小 => '小',成本 => '$0.42']]; - Craig
@Kon 应该避免更改本地对象的状态。这可能会导致与其他库发生冲突(例如麻烦的库PrototypeJs)。相反,我建议使用包装器或同时传递数组和所需属性,例如Dojo和YUI。 - fncomp
@Josh - 我既不是Projotype的粉丝也不是敌人,但我认为它并不是一个麻烦的库,例如,它对原生Array对象的干扰通常只会对糟糕的客户端代码造成问题...比如当人们试图将数组用作关联数组时,或者在没有使用hasOwnProperty()的情况下进行for in循环等。 - nnnnnn
显示剩余2条评论

1

除非你将字符串索引复制到数字索引,否则你无法这样做,但它们会成为数组中的新元素。


0

您没有说明如何创建数组或分配这些值,但听起来您不知道JavaScript数组和JavaScript对象之间的区别。

对象具有带有字符串键的属性,但您无法使用索引整数访问这些属性,只能通过键访问。

数组是一种特殊类型的对象,提供类似于length属性和一些方法(例如sort())的数组功能。数组属性通常使用数字索引分配,并且length属性基于这些数字索引属性,但由于数组仍然是对象,因此您也可以使用字符串键分配属性。如果您说myArray ['banana'] = ..,则无法通过索引号访问该'banana'属性。

如果您想要像“香蕉”这样的键,则根本不应该使用数组,而应该使用普通对象。

有很多文章可以更深入地解释这一点;这里是我随机找到的一个链接:http://andrewdupont.net/2006/05/18/javascript-associative-arrays-considered-harmful/


我正在PHP中创建数组(数组的数组),然后使用json_encode将其发送到JavaScript,所以我想这是一个对象。 - Craig
啊,PHP 数组和 JS 数组不遵循相同的约定。 - nnnnnn

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