Как я могу использовать синтаксис распространения для копирования свойств объекта из нескольких неизвестных объектов в JavaScript?

#javascript #object #mixins

#javascript #объект #миксины

Вопрос:

Я хотел бы использовать синтаксис распространения для копирования свойств из нескольких неизвестных объектов в один объект. Что-то вроде этого:

 var array = [{a:0}, {b:1}, {c:2}]; // This array could hold any number of objects

// This function should take the objects in the array and use spread syntax to create a new object.
function merge(arr) { /* Code I wish I knew */ } // returns an object

var combo = merge(array);

console.log(combo); // {a:0, b:1, c:2}
 

Я в курсе Object.assign . Я задаю этот вопрос просто для того, чтобы посмотреть, можно ли сделать что-то подобное с помощью синтаксиса распространения. Кроме того, меня интересуют скрытые классы V8. Насколько я понимаю, изменение объекта после его создания отрицательно влияет на производительность скрытого класса. Я читал, что в Spread нет этой проблемы, возможно, потому, что он создает экземпляр объекта со всеми свойствами других объектов.

Ответ №1:

Вы можете использовать комбинацию Array.reduce с Object.assign :

 var array = [{a:0}, {b:1}, {c:2}];

function merge(arr) {
  return array.reduce((x,y) => Object.assign(x, y))
  //
  // per the comments, if we don't want to mutate the original object we can do instead:
  // return array.reduce((x,y) => Object.assign(x, y), {})
}

var combo = merge(array);

console.log(combo); 

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

1. Я бы не рекомендовал Object.assign IMHO, поскольку все объекты в исходном массиве будут изменены (побочный эффект).

2. Мне нужно провести некоторое исследование reduce .

3. В этом фрагменте изменен только первый элемент, но все равно неприятный побочный эффект. Этого можно избежать, передав пустой объект для уменьшения в качестве начального значения. return array.reduce((x,y) => Object.assign(x, y), {})

4. Даже если первое переданное вами значение является пустым объектом, не будет ли оно все равно изменено? Возможно, нет способа сделать это без мутации.

5. @NirAlfasi, вы можете просто передать пустой объект в качестве начального уменьшаемого значения, а не присваивать пустой объект на каждой итерации.

Ответ №2:

Вы можете использовать Array#reduce для итерации массива и объединения дочерних элементов в один объект:

 var array = [{a:0}, {b:1}, {c:2}];

function merge(arr) {
  return arr.reduce((acc, cur) => ({ ...acc, ...cur }));
}

var combo = merge(array);

console.log(combo); 

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

1. Моя единственная проблема заключается в том, что при каждом запуске метода reduce создается новый объект. Он объединяет два элемента и возвращает новый объект, затем объединяет этот объект со следующим объектом и так далее, пока все объекты не будут объединены. Это много объектов для сбора мусора в зависимости от того, сколько объектов вы объединяете.