Merging multiple JavaScript objects with same property names

using the spread operator with two objects

2025-02-18 19:00

On the JavaScript telegram (not my channel, but at the time of writing, it has almost 30,000 subscribers), there was a "challenge" quiz post with this snippet:

const obj1 = { a: 1, b: 2 };
const obj2 = { b: 3, c: 4 };
const mergedObj = { ...obj1, ...obj2 };
console.log(mergedObj);

The channel then proceeded to ask "What is the output?":

  • { a: 1, b: 2, c: 4 }
  • { a: 1, b: 2, c: 3 }
  • { a: 1, b: 3, c: 4 }
  • { a: 1, c: 4 }

The correct answer was (of course?) "c" : { a: 1, b: 3, c: 4 }

But why?

Before we look it up, we could "learn-by-experimenting" and see if we can recognize a pattern. Let's try changing the code a bit:

const obj1 = { a: 1, b: 2, c: 0 };
const obj2 = { b: 3, c: 4 };
const mergedObj = { ...obj1, ...obj2 };
console.log(mergedObj);

The console will log { a: 1, b: 3, c: 4 }

From the last two examples, we can begin to see a pattern:

  • When using the spread operator as above, JavaScript will take the value of the last object that had each property
    • the mergedObj will take obj1's value of a
      • (obj2 did not have a property named a)
    • the mergedObj will then take obj2's value of properties b and c
      • (the value of each property of the most recent object with each property)

Exploring further

Let's explore a little further with more objects that have more properties:

const obj1 = { a: 21, b: 2, c: 0, d: -1, e: true, f: [1, 1, 1] };
const obj2 = { a: 1, b: -1, c: true, e: 0 }
const obj3 = { b: 3, c: 4, e: false, f: true };
const mergedObj = { ...obj1, ...obj2, ...obj3 };
console.log(mergedObj);

Could we guess what would log to the console?

Did we guess: { a: 1, b: 3, c: 4, d: -1, e: false, f: true } ?

Did we guess correctly? Of course we did!

  • a appears last in obj2 so it's 1
  • b appears last in obj3 so it's 3
  • c appears last in obj3 so it's 4
  • d appears last in obj1 so it's -1
  • e appears last in obj3 so it's false
  • e appears last in obj3 so it's true

Back it up with some other documentation?

So now, let's confirm our pattern recognition with some MDN: on the spread syntax article, under the heading "Overriding properties" it says:

"When one object is spread into another object, or when multiple objects are spread into one object, and properties with identical names are encountered, the property takes the last value assigned while remaining in the position it was originally set."

...and there we have it!

Summary

When we have multiple JavaScript objects:

  • If we merge each object using the spread operator into a "merged object":
    • The merged object takes all properties from all objects
    • The final value of each property is "the value of each property of the most recent object with each property"!