这个嵌套循环如何得到这个输出?

How does this nested loop get to this output?

很长一段时间我都在努力理解这个嵌套循环的输出。我真的很想了解它的作用。

我希望它输出:[ [ 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ]

但实际输出是:[ [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ], [ 0, 0, 0, 0, 0, 0 ] ]

在第一个内循环后 row 包含两个 0,应该被推到外循环中的 newArray。看起来这并没有发生,我不明白为什么。第一个元素应该是[0, 0]吧?

我真的希望有人能明白我的意思并解释发生了什么!谢谢!

function zeroArray(m, n) {

  // Creates a 2-D array with m rows and n columns of zeroes
  
  let newArray = [];
  let row = [];
  for (let i = 0; i < m; i++) {
  
    // Adds the m-th row into newArray

    for (let j = 0; j < n; j++) {
      // Pushes n zeroes into the current row to create the columns
      row.push(0);
    }
    // Pushes the current row, which now has n zeroes in it, to the array
    newArray.push(row);
  }
  return newArray;
}

let matrix = zeroArray(3, 2);
console.log(matrix);

您将 row 传递给循环的所有迭代。要实现您想要的效果,行在循环的每次迭代中都必须是唯一的,因此您需要将其移动到第一个循环内。

为了更好地理解这个问题,请阅读 JavaScript 中有关值和参考的更多信息:https://www.javascripttutorial.net/javascript-pass-by-value/#:~:text=JavaScript%20pass%2Dby%2Dvalue%20or%20pass%2Dby%2Dreference&text=It%20means%20that%20JavaScript%20copies,variables%20outside%20of%20the%20function

function zeroArray(m, n) {

  // Creates a 2-D array with m rows and n columns of zeroes
  
  let newArray = [];
  for (let i = 0; i < m; i++) {
    let row = [];
  
    // Adds the m-th row into newArray

    for (let j = 0; j < n; j++) {
      // Pushes n zeroes into the current row to create the columns
      row.push(0);
    }
    // Pushes the current row, which now has n zeroes in it, to the array
    newArray.push(row);
    // Update n to get desired pattern
    n += 2
  }
  return newArray;
}

let matrix = zeroArray(3, 2);
console.log(matrix);

那是因为 JavaScript 对象(和数组)只是内存中的一个引用。所以你正在创建一个单一的数组数组,它​​们在内存中共享相同的地址,因为它们共享相同的地址,当你更新它时(Array.prototype.push),你正在更新所有的数组。解决方案是在第一个循环中创建一个新行:

function zeroArray(m, n) {  
  const newArray = [];

  for (let i = 0; i < m; i++) {
    // If this isn't the first run, take the last value of row
    const prevRow = i > 0 ? newArray[i-1] : [];
    const row = [...prevRow]; // By using the spread operator(...), you can copy an array

    for (let j = 0; j < n; j++) {
      // Pushes n zeroes into the current row to create the columns
      row.push(0);
    }
    // Pushes the current row, which now has n zeroes in it, to the array
    newArray.push(row);
  }
  return newArray;
}

let matrix = zeroArray(3, 2);
console.log(matrix);

重要提示

这不是一种自然的书写方式 JavaScript,您可以通过以下方式实现相同的效果:

const zeroArray = (m, n) => Array.from({ length : m }).map((value, index) => {
  return Array.from({ length : (index + 1) * n }).map(() => 0);
});