Разница между заливкой и заполнением карты - PullRequest
6 голосов
/ 21 июня 2019

Я наткнулся на некоторый код, который заполнял массив объектов примерно так:

const getObj = () => {
  return {a: 1, b: 2, c: 3};
}

const arr = Array(3).fill(null).map(getObj);
console.log(arr);

Однако мне интересно, какова основная цель fill(null).map(getObj)? Это кажется излишним, так как я могу просто написать следующее и получить тот же результирующий массив:

const getObj = () => {
  return {a: 1, b: 2, c: 3};
}

const arr = Array(3).fill(getObj());
console.log(arr);

Итак, мне интересно, эти две строки кода выполняют одно и то же или я что-то упускаю?

Результирующие массивы (первый метод верхнего массива с fill + map нижний массив использует только map):

enter image description here

Ответы [ 2 ]

6 голосов
/ 21 июня 2019

Array(3).fill(getObj()) заполнит ваш массив ссылками на тот же объект, Array(3).fill(null).map(getObj) создаст объект для каждого элемента.Смотрите пример ниже:

const getObj = () => {
  return {a: 1, b: 2, c: 3};
}

const arr = Array(3).fill(null).map(getObj);
arr[0].b=4;
console.log(JSON.stringify(arr));

const arr1 = Array(3).fill(getObj());
arr1[0].b=4;
console.log(JSON.stringify(arr1))
1 голос
/ 21 июня 2019

Когда дело доходит до Array.fill , в документации указано, что:

Когда заполняется, передается объект, он копирует ссылку и заполняет массивссылки на этот объект.

Таким образом, использование Array.fill с объектами имеет несколько ограниченное применение, если вы действительно не хотите иметь несколько объектов, указывающих на одну и ту же ссылку .Однако в более чем нескольких случаях использования это приведет к bugs, если не будет понято.


Для второго случая, когда вы делаете Array(3).fill(null).map(getObj), это один из способов создать новый массив на основе заданного произвольного размера и в то же время заполнить его новыми объектами.

Реальная потребность в fill(null) связана с тем фактом, что вызов Array(3) будет делать только одно.Создайте новый массив и установите для его свойства length значение 3. Вот и все!

let arr = Array(3) // returns new array with its "length" property set to 3

console.log(arr)  // [empty × 3]  <-- browser console

Так что этот массив теперь имеет только длину и группу empty элементов.Вы не можете ничего с этим поделать, пока у него не появятся ценности.Следовательно, необходимо fill, чтобы вы задали ему любое значение, а затем map, чтобы установить значения, которые вы на самом деле хотите.Используя Array.map и вызывая каждую итерацию, ваша функция гарантирует, что у вас нет одинаковых ссылок.Вы могли бы пропустить шаг fill и сделать что-то вроде этого:

const getObj = () => ({a: 1, b: 2, c: 3})

// using array destructuring
let arr = [...Array(3)].map(getObj)
arr[0].a = 3
console.log(arr)

// using Array.from
let arr2 = Array.from(Array(3)).map(getObj)
arr2[0].a = 3
console.log(arr2)

Есть несколько короче и вы получите точно такой же результат заполнения массива заданной длиной объектами, а не ссылками на один и тот же объект.

Хитрость в том, что оба будут «заполнять» массив после того, как он будет определен с undefined значениями, после чего map будет заполнять его желаемыми значениями.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...