Неожиданный результат вложенного цикла JavaScript

#javascript #nested-loops

#javascript #вложенные циклы

Вопрос:

Я бы ожидал, что следующий код вернет результат (матрицу)

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

 function zeroArray(m, n) {
  let newArray = [];
  let row = [];
  for (let i = 0; i < m; i  ) {
    
    for (let j = 0; j < n; j  ) {
      row.push(0);
    }
    newArray.push(row);
  }
  return newArray;
}

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

но он возвращает:
[ [0,0,0,0,0,0], [0,0,0,0,0,0], [0,0,0,0,0,0] ]

Я не вижу, как row [0,0,0,0,0,0] для каждой итерации внешнего цикла?

Я вижу row итерацию от [0,0] до [0,0,0,0] до [0,0,0,0,0,0] и нажатие newArray на каждый экземпляр. Однако это, очевидно, неверно.

Кто-нибудь может объяснить мне этот результат?

Комментарии:

1. Это происходит потому, что массивы являются ссылочными типами в JavaScript (то есть, когда вы это делаете newArray.push(row) , вы только нажимаете ссылку на row so, когда ее значение изменяется, оно меняется везде).

2. Хорошо, я понял! Я вижу, что это то, на что вам нужно обратить внимание .. по значению или по ссылкам на эффекты. Я не был полностью осведомлен о том, что ссылка была сохранена на переменную после ввода в массив, я думал, что это новое пространство памяти.. но явно нет. Спасибо

Ответ №1:

Вы могли бы отправить копию row . Это устраняет ту же ссылку на объект.

 function zeroArray(m, n) {
  let newArray = [];
  let row = [];
  for (let i = 0; i < m; i  ) {
    
    for (let j = 0; j < n; j  ) {
      row.push(0);
    }
    newArray.push([...row]);
  }
  return newArray;
}

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

Ответ №2:

Проверка границ была неправильной во внутреннем цикле в соответствии с вашими выводами, на каждой итерации внешнего цикла выделяйте новый массив i * 2 длины.

Вы можете использовать Array.prototype.fill для большего упрощения своего кода.

 function zeroArray(m, n) {
  const newArray = [];
  for (let i = 1; i <= m; i  ) {
    const row = new Array(i * 2).fill(0);
    newArray.push(row);
  }
  return newArray;
}

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

Ответ №3:

Ваш внутренний цикл выполняется для каждого значения n, а затем снова для каждого значения m во внешнем цикле.

Для каждого числа в M> Запустите каждое число в N и нажмите на строку. 3 * 2 дает 6 результатов в этой таблице.