JS,数组矩阵和forEach行为的差异

时间:2018-10-12 18:46:53

标签: javascript arrays foreach

我正在为我的JS课程做一些培训任务,但我得到了一个必须执行一个函数,该函数必须采用正整数(n)并返回类似下面的矩阵(已传递5):

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

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

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函数遍历嵌套在每行中的所有元素(它不应该这样做)一样。

谢谢您的任何建议!

3 个答案:

答案 0 :(得分:3)

这是因为Array是引用类型。

new Array(n).fill(new Array(n).fill(0))

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

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

答案 1 :(得分:0)

有问题的代码与此等效:

let n = 5
let innerArr = new Array(n).fill(0)

function getIdentityMatrix(n) {
  const mat = new Array(n).fill(innerArr);
  return mat.map((row, index) => {
    row[index] = 1;
    return row;
  });
}
console.log(getIdentityMatrix(n))

因为您使用的是fill,所以基本上是在mat数组中引用了innerArr (which you can see clearly from the above console output)

然后对每个i进行row[index] = 1 ,这将更改同一数组的相同值(在i索引处)

现在您的工作示例...可以用以下简短形式编写:

const getIdentityMatrix = (n) =>
   [...Array(n)].map((row, index) => {
     row = Array(n).fill(0)
     row[index] = 1
     return row
   })

console.log(getIdentityMatrix(3))

清楚地maps覆盖了n的新创建数组,然后spreaded,但是然后用全新的数组引用覆盖了每个元素

由于该引用是全新的,因此当我们从地图上row[index] = 1进行修改时,使用return the x对其进行修改会产生预期的行为。

另一种实现这一目标的方法是通过mapObject.assignObject.values这样:

const gm = (n) => [...Array(n)].map((x,i) => 
   Object.values(Object.assign(Object.assign({}, Array(n).fill(0)), {[i]:1})))

console.log(gm(3))

答案 2 :(得分:-2)

// 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次数组。