为什么对单元格所做的更改会传播到此使用 fill 创建的二维数组中的其他单元格?



我对JS中的这个二维数组有问题。当我改变a[1][0]时,a[0][0]随之改变。我初始化它的方式有问题吗?如果是,如何正确初始化它?

>var a = Array(100).fill(Array(100).fill(false));
>a[0][0]
>false
>a[1][0]
>false
>a[1][0] = true
>true
>a[1][0]
>true
>a[0][0]
>true
var a = Array(100).fill(Array(100).fill(false));

a包含一个数组,每个数组元素都引用一个数组。 您正在用一个包含所有 false 值的数组填充外部数组。内部数组只创建一次,对同一数组的引用传递给外部数组的每个元素,这就是为什么如果你对一个元素执行操作,它也会反映在其他元素上。

这实际上相当于

var a1 = Array(100).fill(false);
var a = Array(100).fill(a1);

在这里a得到 100 个元素,它们都引用了同一个数组a1。因此,如果您更改a的一个元素,则所有元素都会更改,因为它们是对同一数组的引用。

您需要用一个新数组填充外部数组中的每个元素。 你可以做这样的事情:

var a = [];
for(var i=0; i<100; i++)
a.push(Array(100).fill(false));

您的整个数组将填充对同一(二维(数组对象的引用。

要用不同的对象填充它,你必须做这样的事情:

const a = Array(100).fill(false).map(x => Array(100).fill(false));
a[0][0] = true;
console.log(a[0][0]);
console.log(a[0][1]);
console.log(a[1][1]);

请注意,初始数组中的值需要显式设置为某些值(在我的示例中false,但也可以undefined(,因为构造函数创建的数组是稀疏的,并且map()函数将仅对实际存在的属性进行操作。

要解决此问题,您可以使用Array.from()

const a = Array.from(Array(100), x => Array(100).fill(false));
a[0][0] = true;
console.log(a[0][0]);
console.log(a[0][1]);
console.log(a[1][1]);

您的问题是您在第一个数组的每个位置都使用第二个Array(100).fill(false)。这就是为什么当您更改"第二个"维度中的一个值时,它将在数组的每个位置发生变化。如果你想避免这种情况,你必须为初始的每个位置创建一个新的数组。

var x = Array(100).fill().map(x => Array(100).fill(false));

您在这里所做的是在较大数组的每个索引处添加相同的数组对象。

所以当你这样做时

Array(x).fill(Array(y).fill(false));

你实际上正在做的是:

Array(x).fill(Y); // i.e. X.fill(Y)

现在,每当您更改 Y 时,您将在 X 的每个索引处获得相同的值。

当数据本身是一个对象时,你应该使用循环来填充数据(记住数组是对象(。

这些看起来像是一个重复的问题,但我总是使用这样的东西

var x = new Array(10);
for (var i = 0; i < 10; i++) {
x[i] = new Array(10).fill(false);
}
x[5][5] = true

信用:如何在 JavaScript 中创建二维数组?

由于数组是引用类型,因此在JS中创建N维数组并非易事。您需要先创建一个克隆工具。

Array.prototype.clone = function(){
return this.map(e => Array.isArray(e) ? e.clone() : e);
};
function arrayND(...n){
return n.reduceRight((p,c) => c = (new Array(c)).fill().map(e => Array.isArray(p) ? p.clone() : p ));
}
var arr = arrayND(2,3,4,"x")
console.log(JSON.stringify(arr));

arrayND 采用无限数量的整数参数,每个参数指定维度的大小,最后一个参数是填充值。

mdn 中所述的填充函数将相同的值复制到所有数组索引。您可以使用以下实用程序创建阵列的克隆。但是由于我使用的是切片运算符,因此这仅限于克隆数组。

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/fill

if (!Array.prototype.clonefill) {
Object.defineProperty(Array.prototype, 'clonefill', {
value: function(value) {
// Steps 1-2.
if (this == null) {
throw new TypeError('this is null or not defined');
}
var O = Object(this);
// Steps 3-5.
var len = O.length >>> 0;
// Steps 6-7.
var start = arguments[1];
var relativeStart = start >> 0;
// Step 8.
var k = relativeStart < 0 ?
Math.max(len + relativeStart, 0) :
Math.min(relativeStart, len);
// Steps 9-10.
var end = arguments[2];
var relativeEnd = end === undefined ?
len : end >> 0;
// Step 11.
var final = relativeEnd < 0 ?
Math.max(len + relativeEnd, 0) :
Math.min(relativeEnd, len);
// Step 12.
while (k < final) {
O[k] = value.slice(0);
k++;
}
// Step 13.
return O;
}
});
}
Array(100).clonefill(Array(100))
a[0][0] = true
a[1][0]
false

最新更新