#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 создается новый объект. Он объединяет два элемента и возвращает новый объект, затем объединяет этот объект со следующим объектом и так далее, пока все объекты не будут объединены. Это много объектов для сбора мусора в зависимости от того, сколько объектов вы объединяете.