Вот хитрый вопрос:
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
, который передается по ссылке, поскольку каждая итерация использует новую область.
Если бы вы инициализировали []
снаружи и передали его... тогда мы вернулись бы к исходной точке.