Javascript 二维数组
我使用下面的代码创建一个最初填充了false的布尔值的二维数组,然后分别翻转该值Javascript 二维数组,javascript,arrays,reactjs,Javascript,Arrays,Reactjs,我使用下面的代码创建一个最初填充了false的布尔值的二维数组,然后分别翻转该值 constructor(props) { super(props); this.state = { fullGrid: Array(3).fill(Array(5).fill(false)) }; this.toggleFullGrid = this.toggleFullGrid.bind(this); } //Toggles boolean value found at id togg
constructor(props) {
super(props);
this.state = {
fullGrid: Array(3).fill(Array(5).fill(false))
};
this.toggleFullGrid = this.toggleFullGrid.bind(this);
}
//Toggles boolean value found at id
toggleFullGrid(cols, rows) {
alert("This is index.js, we got everything: " + cols + " " + rows);
let alteredGrid = this.state.fullGrid;
console.log(alteredGrid);
console.log(cols + " " + rows);
console.log(alteredGrid[cols][rows]);
//change alteredGrid at cols,rows
alteredGrid[cols][rows] = !alteredGrid[cols][rows];
console.log(alteredGrid);
this.setState({fullGrid: alteredGrid});
}
但是,这会导致整个列以非常混乱的方式翻转,而不是翻转单个值。以下是控制台输出:
(3) [Array(5), Array(5), Array(5)]
0 : (5) [true, false, false, false, false]
1 : (5) [true, false, false, false, false]
2 : (5) [true, false, false, false, false]
length : 3
__proto__ : Array(0)
index.js:21 0 0
index.js:22 false
index.js:26
(3) [Array(5), Array(5), Array(5)]
0 : (5) [true, false, false, false, false]
1 : (5) [true, false, false, false, false]
2 : (5) [true, false, false, false, false]
length : 3
__proto__ : Array(0)
第一个数组是翻转前的一个副本,所以我不确定为什么它不全是假的。第二个和第三个输出证明程序知道它在翻转什么和在哪里。第四个输出第二个阵列与第一个阵列相同
此外,它也不是真正的更新。状态更改应该强制其他元素根据它们是否对应于数组中的true或false进行更新和更改颜色,但这不会发生
问:为什么要翻转整个专栏?为什么第一个输出的数组与第二个输出的数组相同?我如何让它翻转单个值?我如何让它正确更新
另外,有人告诉我,在javascript中,当试图翻转值时,数组会发生奇怪的事情,所以我测试了一个版本,在这个版本中,我将数组值保存到一个单独的变量,翻转它,然后将它保存回来。结果是相同的。似乎是您使用Array.fill的方式导致了问题 原因是,只有一行在内部被引用了三次。因此,当您更改任何行中的任何单元格时,其他行中的特定单元格也会更改 可以按如下方式使用数组填充:
this.state = {
fullGrid : Array(3).fill(0).map(row => new Array(5).fill(false))
}
上面的解决方案将首先创建一个0的数组,然后用一个新数组映射每一行,您可以在其中填充false
您还可以测试:
var a = new Array(3).fill(new Array(5).fill(false));
(3) [Array(5), Array(5), Array(5)]
0 : (5) [false, false, false, false, false]
1 : (5) [false, false, false, false, false]
2 : (5) [false, false, false, false, false]
length : 3
__proto__ : Array(0)
如果你这样做
a[0][0] = true
现在a将成为:
(3) [Array(5), Array(5), Array(5)]
0 : (5) [true, false, false, false, false]
1 : (5) [true, false, false, false, false]
2 : (5) [true, false, false, false, false]
length : 3
__proto__ : Array(0)
由于该值是通过引用更改的,因此每行的第一个单元格都变为true
您的console.log输出是相同的,因为console.log以异步方式发生
欢迎来到神奇的sic!Javascript数组、引用和可变对象的世界 回答:为什么要翻转整个专栏 数组的工作方式不同于复制数据的简单值布尔值、字符串和数字。当您为一个变量分配一个数组时,您只分配了它的引用,而不是实际的对象。javascript中的所有非原语值都是对象 所以按照你写的: Array3.fillArray5.fillfalse是两个语句: Array5.fillfalse 阵列3.填充。。。 在第一个数组中,创建一个填充false的Array5,在第二个数组中,使用相同的Array5填充新的Array3 3次 因此,当您更改数组[0][0]时,实际上是在修改它后面的同一个对象,并且您发现自己更改了三个不同的引用,但仍然是相同的,并且只有以前创建的数组5 回答:为什么第一个输出的数组与第二个输出的数组相同 因为console.log不会冻结显示的值,而且如果它通常适用于简单值,则不会立即冻结。在控制台中打印值所需的时间,原始数组已被更改。由于打印引用,此引用将反映应用于其值的更改 我很抱歉,如果它不是真正可以理解的,因为我很难正确地解释它是如何作为英语工作的,因为它不是我的母语 回答:我如何让它翻转单个值?我如何让它正确更新 您需要使用不可变的值 首先,创建一个真正不可变的状态:
const array5 = Array(5).fill(false);
this.state = {
fullGrid: Array(3).fill(null).map(() => array5.slice())
};
然后,在处理您的状态时,还要复制要处理的新阵列:
let alteredGrid = this.state.fullGrid.slice();
现在,您可以安全地设置新的清洁状态,该状态将正确替换旧状态