How-To

How-To · Objects

How to Merge Objects in JavaScript

Merge two or more objects with the spread operator or Object.assign(), understand how key conflicts resolve, and know why both do a shallow merge.

XCODXHow-To · Updated

Overview

To combine the properties of several objects into one, JavaScript gives you two tools: the spread operator { ...a, ...b } and Object.assign(). Spread is the modern default because it always produces a new object; Object.assign() is the older method and can either build a new object or write into an existing one. Both do a shallow merge, and both resolve key conflicts the same way — the last object wins.

Steps

1. Merge with the spread operator

Spreading each object into a new literal copies all their own enumerable properties into one fresh object. This is the cleanest way to merge because it never touches the sources — you always get a brand-new object back.

const a = { a: 1 };
const b = { b: 2 };

const merged = { ...a, ...b };
console.log(merged); // { a: 1, b: 2 }

2. Understand how conflicts resolve

When two objects have the same key, the later one in the spread order overwrites the earlier. This is what makes spread perfect for applying overrides or defaults: list the defaults first and the overrides last.

const defaults = { theme: 'light', size: 'md' };
const prefs = { theme: 'dark' };

console.log({ ...defaults, ...prefs });
// { theme: 'dark', size: 'md' } — prefs override defaults

3. Merge with Object.assign()

Object.assign(target, ...sources) copies the sources into target and returns it. Pass a fresh {} as the target to build a new object without mutating anything — always do this unless you specifically intend to modify the target in place.

const a = { a: 1 };
const b = { b: 2 };

const merged = Object.assign({}, a, b);
console.log(merged); // { a: 1, b: 2 }
console.log(a);      // { a: 1 } — untouched, thanks to the {} target

In practice, prefer spread for its clarity and immutability, and reach for Object.assign() only when you must write into an existing object — updating a config in place, say — or when merging a variable number of sources you already hold in an array, where Object.assign({}, ...list) reads more naturally than repeated spreads. The two produce identical results for the same inputs; the choice is about mutation and style, not behavior.

One more nuance: merging preserves the key order you'd expect. Keys from earlier objects keep their position, a later object that overrides a key updates the value without moving it, and genuinely new keys are appended at the end. That stability matters whenever the object's order is visible — a rendered form, a serialised JSON payload, a set of columns.

Runnable example

The complete, runnable version — edit the objects and watch conflicts resolve:

Common pitfalls

Both approaches copy only own enumerable properties, and both trigger setter functions on the target — edge cases you rarely hit with plain data objects, but worth knowing exist when merging class instances.

Frequently asked questions

What's the easiest way to merge two objects in JavaScript?
Use the spread operator: const merged = { ...a, ...b }. It returns a new object and, on key conflicts, keeps the value from the rightmost object.
Which value wins when merged objects share a key?
The later object in the merge order wins. In { ...a, ...b } and Object.assign({}, a, b), b's value overwrites a's for any shared key.
Does merging objects modify the originals?
Spread never mutates the sources. Object.assign(target, ...) mutates the target, so pass a fresh {} as the target to avoid changing your input objects.
Why isn't my nested object being deep-merged?
Spread and Object.assign are shallow — a shared nested key is replaced wholesale, not merged. Deep-merge by recursing manually or using a utility like lodash merge.