我目前正在做一些非常基本的事情,但我很难过。我希望在二维数组中得到一个随机索引,并在每次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数组吗?
感谢。
答案 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
是一个数组,其唯一有效索引为dieTwo
,undefined
超出范围。遗憾的是,数组返回undefined
而不是抛出错误。"undefined"
被强制转换为字符串,因此可以将其用作属性键。从技术上讲,只有字符串才是属性键;根据标准,阵列有点伪造。值为dice["undefined"]
。++
分配值,因此undefined
首次尝试将其初始值视为undefined
。而且,不幸的是,它不是抛出异常,而是将0
强制转换为您想要的内容,数字1
,递增到dice["undefined"]
,并将其分配给新定义的{{} 1}}。
undefined++
将为NaN
。[dieOne][dieTwo]
始终强制为"undefined"
,所述dice
的属性在循环的每次迭代中递增一次,使其最终值为{{ 1}}。
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]
是一个我们可以有意义地增加的数字。