我在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
答案 0 :(得分:17)
var a = Array(100).fill(Array(100).fill(false));
a
包含一个数组,每个数组都引用一个数组。您正在使用包含所有错误值的数组填充外部数组。内部数组只进行一次,并且对同一数组的引用被传递给外部数组的每个元素,这就是为什么如果对一个元素执行操作,它也会反映在其他元素上。
这实际上相当于
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));
答案 1 :(得分:7)
您的整个数组将填充对相同(第二维)数组对象的引用。
要用不同的对象填充它,你必须做这样的事情:
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]);
&#13;
请注意,初始数组中的值需要显式设置为某些内容(在我的示例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]);
&#13;
答案 2 :(得分:3)
您的问题是您在第一个阵列的每个位置使用第二个Array(100).fill(false)
。这就是为什么当你在&#34;第二个&#34;中更改一个值时尺寸将在阵列的每个位置发生变化。如果你想避免这种情况,你必须为初始的每个位置创建一个新的数组。
var x = Array(100).fill().map(x => Array(100).fill(false));
答案 3 :(得分:2)
你在这里做的是在更大数组的每个索引处添加相同的数组对象。
所以当你这样做时
Array(x).fill(Array(y).fill(false));
你实际做的是:
Array(x).fill(Y); // i.e. X.fill(Y)
现在,无论何时更改Y,您都会在X的每个索引处获得相同的值。
当数据本身是一个对象时,你应该使用循环来填充数据(记住Array是对象)。
答案 4 :(得分:1)
这些似乎是一个重复的问题,但我总是只使用这样的东西
var x = new Array(10);
for (var i = 0; i < 10; i++) {
x[i] = new Array(10).fill(false);
}
x[5][5] = true
答案 5 :(得分:1)
由于数组是引用类型,因此在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));
&#13;
arrayND采用无限数量的整数参数,每个参数指定一个维度的大小,最后一个参数是填充值。
答案 6 :(得分:0)
mdn中描述的fill函数将相同的值复制到所有数组索引。您可以使用以下实用程序来创建阵列的克隆。但由于我使用切片运算符,因此仅限于克隆数组。
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