Вот хитрый вопрос:

const arr = Array(5).fill([]);
const arr2 = arr.map((subArr, i) => subArr.push(i));

Каково конечное значение arr? И окончательное значение arr2?

Это может быть то, что люди спрашивают в интервью… и прежде чем вы пойдете console.log({ arr, arr2 }), важно знать why больше, чем ответ.

array — это значение, которое всегда будет передаваться «в качестве ссылки», что означает, что оно указывает куда-то в память и просто использует это.

Напротив, такие значения, как string или number, передаются «по значению», то есть копируются туда, где это необходимо.

И как бы странно это ни казалось, когда вы говорите это fill с [], вы говорите Javascript использовать одну и ту же ссылку во всех экземплярах.

Итак, когда вы сопоставляете, вы нажимаете индекс на одну и ту же ссылку снова и снова.

А что тогда со вторым?

Ну… это еще больше хитрости! Потому что это именно то, что возвращает push!

И если вы не знали… push возвращает длину массива после нажатия.

И поскольку он находится внутри map, он возвращает новый массив... легко понять, что происходит.

Результат

И поэтому он печатает это:

{
  arr: [[0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4]],
  arr2: [1, 2, 3, 4, 5]
}

И не буду врать…

Это произошло не из интервью или чего-то подобного… но из теста, который я делал, как вы могли себе представить, делал не то, что хотел.

«Исправить»:

const arr = Array(5).fill().map(() => []);
const arr2 = arr.map((subArr, i) => subArr.push(i));
console.log({ arr, arr2 });
/*
  {
    arr: [ [ 0 ], [ 1 ], [ 2 ], [ 3 ], [ 4 ] ],
    arr2: [ 1, 1, 1, 1, 1 ]
  }
*/

Просто Array(5).map(() => []) не работает, так как Array(n) создает массив «пустых слотов», к которым вы можете получить прямой доступ, но вы не можете сделать ничего другого, поэтому вам нужно fill(), чтобы заменить эти «пустоты» на undefined.

Почему это работает?

Это работает, потому что map перебирает массив, и каждый из [] на самом деле является объектом new, который передается по ссылке, поскольку каждая итерация использует новую область.

Если бы вы инициализировали [] снаружи и передали его... тогда мы вернулись бы к исходной точке.

Фото на обложке Natalia Y на Unsplash