javascript 二维数组中出现意外值

4xy9mtcn  于 2023-05-05  发布在  Java
关注(0)|答案(3)|浏览(194)

这可能是一个重复的问题,但我不知道如何搜索它。
有人能解释一下代码片段中的bevior吗?
我尝试迭代一个二维数组,将每个值设置为包含行的索引。然而,所有值都以某种方式设置为最后一行的索引。

const string1 = "abc";
const string2 = "abcd";

const matrix = new Array(string1.length).fill(new Array(string2.length).fill(0));

for (let i = 0; i < string1.length; i++) {
  for (let j = 0; j < string2.length; j++) {
    console.log(i);
    matrix[i][j] = i;
  }
}

console.log(matrix);

输出:

0
0
0
0
1
1
1
1
2
2
2
2
[ [ 2, 2, 2, 2 ], [ 2, 2, 2, 2 ], [ 2, 2, 2, 2 ] ]

预期输出:

0
0
0
0
1
1
1
1
2
2
2
2
[ [ 0, 0, 0, 0 ], [ 1, 1, 1, 1 ], [ 2, 2, 2, 2 ] ]
pkmbmrz7

pkmbmrz71#

请参阅文档:
fill()将数组的所有值更改为静态value。[...]注意数组中的所有元素都是这个精确值:如果value是一个对象,则数组中每个插槽都将引用该对象。
这意味着在你的每一行中,你将引用相同的对象(= Array,记住:数组是JavaScript中的对象),这意味着你总是改变同一个数组,导致最后一次改变是你可以通过打印它来观察的。

const string1 = "abc";
const string2 = "abcd";

const matrix = new Array(string1.length).fill(new Array(string2.length).fill(0));

for (let i = 0; i < string1.length; i++) {
  for (let j = 0; j < string2.length; j++) {
    matrix[i][j] = i;
  }
}

console.log(JSON.stringify(matrix));
// Prove that they are actually the same reference => same object
console.log(matrix[0] === matrix[1]) // true

可以使用以下方法初始化数组。

const string1 = "abc";
const string2 = "abcd";

const matrix = [...new Array(string1.length)].map((_, i) => new Array(string2.length).fill(i));

console.log(JSON.stringify(matrix));

// now we have different references => different objects
console.log(matrix[0] === matrix[1]) // returns false
dxxyhpgq

dxxyhpgq2#

问题是在发布的代码中,对

.fill(new Array(string2.length)

在计算fill的参数时创建一个数组,这意味着fill将调用它的数组的所有元素设置为同一个Array对象。
这样,这个代码片段创建第二维数组只涉及为matrix的第一维数组创建一个数组:

const string1 = "abc";
const string2 = "abcd";
const matrix = new Array(string1.length).fill(0);
matrix.forEach( (_, i, rows) => rows[i] = new Array(string2.length).fill(i));
console.log( matrix)

console.log("\nSee note about spread for this: ", [...new Array(string1.length)]);

注意事项

  • 数组原型方法(如forEachmap)不处理它们所调用的数组中的空槽(即它们跳过尚未被分配值的数组条目)。
  • 代码段中matrix声明末尾的fill(0)调用确保其插槽都不为空。(它可以使用不带参数的fill()来用undefined填充空插槽)。
  • 使用spread语法从一个数组初始化另一个数组,将 * spread数组中的空槽 * 转换为初始化数组中值为undefined的元素,这一点很有趣,但在代码片段中没有使用。
4sup72z8

4sup72z83#

也许下面的解决方法将有助于获得最终结果。

const string1 = "abc";
const string2 = "abcd";

const matrix = [];

for (let i = 0; i < string1.length; i++) {
    const arrayJ = [];
    for (let j = 0; j < string2.length; j++) {
        arrayJ.push(i);
    }
    matrix.push(arrayJ);
}

console.log(matrix);

相关问题