Javascript 数组矩阵和forEach行为的差异

Javascript 数组矩阵和forEach行为的差异,javascript,arrays,foreach,Javascript,Arrays,Foreach,我在为我的JS课程做一些培训任务,我得到了一个必须实现一个函数的任务,该函数接受一个正整数(n)并返回一个如下矩阵(传递了5个): 我能够使用以下代码实现该功能: function getIdentityMatrix(n) { const mat = new Array(n).fill([]); return mat.map((row, index) => { row = new Array(n).fill(0); row[index] = 1; retur

我在为我的JS课程做一些培训任务,我得到了一个必须实现一个函数的任务,该函数接受一个正整数(n)并返回一个如下矩阵(传递了5个):

我能够使用以下代码实现该功能:

function getIdentityMatrix(n) {
  const mat = new Array(n).fill([]);
  return mat.map((row, index) => {
    row = new Array(n).fill(0);
    row[index] = 1;
    return row;
  });
}
但在做这件事的时候,我发现了一种奇怪的行为,我无法解释。。。如果我稍微修改一下代码:

function getIdentityMatrix(n) {
  const mat = new Array(n).fill(new Array(n).fill(0));
  return mat.map((row, index) => {
    row[index] = 1;
    return row;
  });
}
它返回如下矩阵:

[ [ 1, 1, 1, 1, 1 ],
  [ 1, 1, 1, 1, 1 ],
  [ 1, 1, 1, 1, 1 ],
  [ 1, 1, 1, 1, 1 ],
  [ 1, 1, 1, 1, 1 ] ]
为什么会这样?这就像forEach函数迭代嵌套在每行中的所有元素一样,它不应该这样做


谢谢你的建议

这是因为数组是引用类型。当你这样做的时候

新数组(n).fill(新数组(n).fill(0))

首先,内部的
新数组(n).fill(0)
使数组大小n填充
0
;接下来,外部
数组(n).fill创建一个数组,该数组中填充了对该内部数组的n个引用

它不创建n个内部数组,只创建n个对同一数组的引用。因此,当您更改该内部数组的元素时,外部数组中的所有引用都将反映更改,因为它们都指向同一对象

// your example is roughly equivalent to this.
const innerArray = new Array(n).fill(0);
const mat = new Array(n).fill(innerArray);

(mat[0] === mat[1] === innerArray) === true;

只有1个嵌套数组,而不是n次数组。

所讨论的代码与此等效:

设n=5
让innerArr=新数组(n).填充(0)
函数getIdentityMatrix(n){
const mat=新数组(n).fill(innerArr);
返回mat.map((行,索引)=>{
行[索引]=1;
返回行;
});
}

console.log(getIdentityMatrix(n))
问题是外部数组中的每个索引都包含对内部数组的相同引用。当您将非原语传递给
.fill()
时,数组的每个索引都将引用相同的对象。你有一个5个对同一个内部数组的引用的数组。因为这不是一个完整的答案,所以我将此作为一个注释发布。一个合适的单行替换将是
const mat=[…Array(n).keys()].map(()=>Array(n).fill(0))
@patrick我更喜欢
Array.from({length:n},(1)=>Array.from({length:n},(2)=>+(i1==i2))@jonaswillms我认为这比我的更难理解,尽管它确实取代了整个函数,而不仅仅是错误的行。我还做了另一个:
[…数组(n).keys()].map(I=>Object.assign(数组(n).fill(0),{[I]:1}))
;)
// your example is roughly equivalent to this.
const innerArray = new Array(n).fill(0);
const mat = new Array(n).fill(innerArray);

(mat[0] === mat[1] === innerArray) === true;