这虽然(不幸的是)在技术上是有效的 JavaScript,但不会做你想做的事:
dice[[dieOne][dieTwo]]
该表达式foo[bar]
是对foo
名为 的属性的引用bar
。属性键始终是字符串或数字(技术上只是字符串,但如果我们谈论的是数组,将键视为数字更有意义)。因此,当 JavaScript 看到表达式时dice[[dieOne][dieTwo]]
,它会尝试强制[dieOne][dieTwo]
转换为有效的属性键。古怪的情况如下:
[dieOne]
计算结果为一个数组,该数组包含一个索引为 0 的元素,其值为dieOne
; 让该中间结果在下文中称为foo
。
foo[dieTwo]
foo
计算对其索引为的属性的引用dieTwo
- 因为,在循环的每次迭代中,
dieTwo
总是 > 0,并且foo
是一个数组,其唯一有效索引是0
,dieTwo
超出范围。可悲的是,数组返回undefined
而不是抛出错误。
- 该值
undefined
被强制转换为字符串,因此可以用作属性键。从技术上讲,只有字符串是属性键;根据标准,数组是伪造的。值为"undefined"
。
- 由于您的代码尚未为 分配值
dice["undefined"]
,因此第一次尝试++
将其初始值再次视为undefined
。同样,不幸的是,它没有抛出异常,而是强制undefined
转换为您想要的样子, number 0
,递增到1
,并将其分配给新定义的dice["undefined"]
。
- 如果您的浏览器遵循 ES5 标准,
undefined++
则为NaN
.
- 由于遵循上述步骤,
[dieOne][dieTwo]
始终强制为,因此在循环的每次迭代中"undefined"
,所述属性dice
都会递增一次,最终值为30000
。
- 如果您的浏览器遵循 ES5 标准,无论您增加多少次,都会是
NaN++
。NaN
- 由于 ANY
[foo][bar]
where bar
is not 0
,当被强制转换为属性键时,将"undefined"
根据上述步骤,dice[[n][m]]
始终等同于dice["undefined"]
. 只是为了好玩,除了验证它不是并且因此我是正确的并且应该得到一个复选标记 =D 之外,尝试绝对是在哪里dice[[n][0]]
。n
"undefined"
30000
所以这就是为什么你会得到那个特定的结果。
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]
可以有意义地增加一个数字。