在JavaScript中增加多维数组

时间:2013-11-02 00:25:59

标签: javascript multidimensional-array

我目前正在做一些非常基本的事情,但我很难过。我希望在二维数组中得到一个随机索引,并在每次for循环翻转时将其递增一。

var dice = [[],[]];

// Get totals.
for(var i = 0; i < 30000; i++) {
    var dieOne = Math.floor(Math.random() * 6 + 1);
    var dieTwo = Math.floor(Math.random() * 6 + 1);
        dice[[dieOne][dieTwo]]++;
    }

    // All index values equal 30,000 for some reason
    alert(dice[[1][3]]);

为什么for循环会将所有索引设置为30,000?我错误地使用JavaScript数组吗?

感谢。

2 个答案:

答案 0 :(得分:2)

您正在做什么

您似乎误解了您正在做的事情的语法。它目前相当于

var dieOne = Math.floor(Math.random() * 6 + 1);
var dieTwo = Math.floor(Math.random() * 6 + 1);
var foo;
foo = dieOne; // a number
foo = [foo];  // an array with one number in it
foo = foo[dieTwo]; // probably undefined, unlikely case of `dieTwo = 0`
                   // which would give back `dieOne`
dice[foo] = dice[foo] + 1; // most likely trying to add 1 to property `undefined`

然后你要做

foo = [1]; // an array length 1
foo = foo[3]; // undefined, it doesn't have an item here
foo = dice[foo]; // = dice[undefined] = undefined
alert(foo); // alerting "undefined"

你可能想做什么

看起来您实际上想要6 数字的每个6 数组数组;构建你最喜欢的方式

var dice = [
    [0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0]
];

然后你的循环

var dieOne, dieTwo, i;
for(i = 0; i < 30000; ++i) {
    dieOne = Math.floor(Math.random() * 6); // indices start at 0 and
    dieTwo = Math.floor(Math.random() * 6); // 6 of them means max is 5
    dice[dieOne][dieTwo]++; // count the brackets here..
}

然后说你想知道你有多少次 dieOne = 1,dieTwo = 3 ,你会看到

dice[1][3]; // count the brackets again.

答案 1 :(得分:1)

虽然(不幸的是)技术上有效的JavaScript,但是不会做你想要的:

dice[[dieOne][dieTwo]]

表达式foo[bar]是对foo名为bar的属性的引用。属性键总是字符串或数字(技术上只是字符串,但如果我们谈论数组,将键视为数字更有意义)。因此,当JavaScript看到表达式dice[[dieOne][dieTwo]]时,它会尝试将[dieOne][dieTwo]强制转换为有效的属性键。 Wackiness如下:

  • [dieOne]求值为一个数组,其中包含一个索引为0的元素,其值为dieOne;让中间结果在下文中称为foo
  • foo[dieTwo]评估对foo索引为dieTwo
  • dieTwo属性的引用
  • 因为,在循环的每次迭代中,foo始终是&gt; 0,0是一个数组,其唯一有效索引为dieTwoundefined超出范围。遗憾的是,数组返回undefined而不是抛出错误。
  • "undefined"被强制转换为字符串,因此可以将其用作属性键。从技术上讲,只有字符串才是属性键;根据标准,阵列有点伪造。值为dice["undefined"]
  • 由于您的代码尚未为++分配值,因此undefined首次尝试将其初始值视为undefined。而且,不幸的是,它不是抛出异常,而是将0强制转换为您想要的内容,数字1,递增到dice["undefined"],并将其分配给新定义的{{} 1}}。
    • 如果您的浏览器符合ES5标准,则undefined++将为NaN
  • 由于遵循上述步骤,[dieOne][dieTwo]始终强制为"undefined",所述dice的属性在循环的每次迭代中递增一次,使其最终值为{{ 1}}。
    • 如果您的浏览器遵循ES5标准,30000将是NaN++,无论您增加多少次。
  • 由于NaN [foo][bar]不是bar的{​​{1}},因此在强制转换为属性键时,根据上述步骤,0"undefined"dice[[n][m]]为总是相当于dice["undefined"]。只是为了好玩,试试dice[[n][0]],其中n绝对不是"undefined",以确认它不是30000,因此我是正确的,值得一个复选标记= D 。

这就是为什么你得到那个特定的结果。

JS中没有真正的多维数组,如果您将其视为数组数组,那么您对语法的困惑就会少得多。然后你可以把它分解成几个步骤:

  • dice是一组数字数组,
  • 所以dice[n]是一个数字数组,
  • 所以dice[n][m]是我想要的号码。

所以这里大致是你的正确程序:

/* We don't like undefined anymore, so make an array of 7 arrays of 7 zeroes */
/* (we need 7 because JS array indexes start at 0 and you're using values 1-6) */
var dice = [
    [0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0],
    [0,0,0,0,0,0,0]
];
/* Now I'm tired of repeating myself, so let's DRY things up */
function roll() {
    return Math.floor(Math.random()*6) + 1;
}
var dieOne, dieTwo;
for ( var i = 0 ; i < 30000 ; i++ ) {
    dieOne = roll();
    dieTwo = roll();
    dice[dieOne][dieTwo]++;
}

最重要的部分是最后一行。

  • dice是一个数组数组,
  • 所以dice[dieOne]是一个数字数组,
  • 所以dice[dieOne][dieTwo]是一个我们可以有意义地增加的数字。