0

I would like to use spread syntax to copy properties from several unknown objects into one object. Something like this:

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}

I am aware of Object.assign. My reason for asking this question is just to see if this sort of thing can be done with spread syntax. Additionally, I'm concerned with V8's Hidden Classes. From what I understand, modifying an object after it is instantiated negatively impacts the performance of the Hidden Class. I've read that Spread doesn't have this issue, possibly because it instantiates the object with all of the properties of the other objects.

Frank
  • 2,050
  • 6
  • 22
  • 40

2 Answers2

2

You can use a combination of Array.reduce with 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);
Nir Alfasi
  • 53,191
  • 11
  • 86
  • 129
  • 1
    I wouldn't recommend `Object.assign` IMHO since all the objects in the original array will be mutated(a.k.a. side-effect). – Hao Wu Feb 09 '21 at 00:47
  • I'm going to have to do some research on `reduce`. – Frank Feb 09 '21 at 00:49
  • 2
    Only the first element is mutated in this snippet, but still a nasty side-effect. This can be avoided by passing an empty object to reduce as an initial value. `return array.reduce((x,y) => Object.assign(x, y), {})` – pilchard Feb 09 '21 at 01:31
  • Even if the first value you pass in is an empty object, wouldn't it still be mutated? Maybe there's no way to do this without mutation. – Frank Feb 09 '21 at 01:58
  • @NirAlfasi, You can simply pass an empty object as the initial reduce value rather than assigning to an empty obect on every iteration. – pilchard Feb 09 '21 at 11:33
  • @pilchard true, we can also: `array.reduce((x,y) => Object.assign(x, y), {})` (I actually wrote it like that in a previous revision and removed it to be more concise. That's definitely an option if mutating the original object is an unwanted side-effect. – Nir Alfasi Feb 09 '21 at 11:54
1

You can use Array#reduce to iterate the array and merge the children into one object:

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);
Hao Wu
  • 17,573
  • 6
  • 28
  • 60
  • 1
    My only issue with this is that it creates a new object every time the reduce method runs. It combines two elements and returns a new object, then combines that object with the next object and so on until all the objects have been merged. That's a lot of objects to garbage collect depending on how many objects you're merging. – Frank Feb 09 '21 at 01:18