Question

How to Merge JavaScript Objects: Object.assign, Spread Syntax, and Practical Patterns

javascriptjavascript-objects

Question

I need to merge two simple JavaScript objects at runtime. For example:

var obj1 = { food: 'pizza', car: 'ford' };
var obj2 = { animal: 'dog' };

// Desired result: obj1 should end up with food, car, and animal

Is there a built-in way to combine the properties of one object into another in JavaScript?

I do not need deep recursion, and I do not need to merge functions. I only need to work with flat objects and copy their properties.

Short Answer

By the end of this page, you will understand how to merge flat JavaScript objects using built-in tools such as Object.assign() and object spread syntax. You will also learn what happens when property names conflict, when the original object is mutated, and which approach is most common in modern JavaScript.

Concept

In JavaScript, objects store data as key-value pairs. Merging objects means taking the properties from one object and copying them into another object.

For flat objects, this is straightforward:

  • Read the properties from a source object
  • Copy them onto a target object
  • If the same property exists in both, the later value usually replaces the earlier one

This matters because object merging is a very common task in real programs. Developers use it to:

  • combine configuration settings
  • update application state
  • build API request options
  • add default values to user input

JavaScript provides built-in ways to do this:

  • Object.assign()
  • object spread syntax: { ...obj1, ...obj2 }

These are ideal for shallow merges. A shallow merge means only the top-level properties are copied. If a property contains another object or array, the inner value is not deeply merged.

In your case, since the objects are simple and flat, a shallow merge is exactly what you need.

Mental Model

Think of each object as a small label sheet.

  • obj1 has labels: food, car
  • obj2 has label: animal

Merging means taking the labels from the second sheet and placing them onto the first sheet.

If both sheets have the same label name, the new label covers the old one.

So object merging is like combining two sets of named fields into one final set.

Take Quiz

Syntax and Examples

Using Object.assign()

const obj1 = { food: 'pizza', car: 'ford' };
const obj2 = { animal: 'dog' };

Object.assign(obj1, obj2);

console.log(obj1);
// { food: 'pizza', car: 'ford', animal: 'dog' }

Object.assign(target, source) copies the enumerable properties from the source object into the target object.

  • obj1 is the target
  • obj2 is the source
  • obj1 is changed directly

Creating a new merged object

If you do not want to change the original object:

const obj1 = { food: 'pizza', car: 'ford' };
const obj2 = { animal: 'dog' };

const merged = Object.assign({}, obj1, obj2);

console.log(merged);
// { food: 'pizza', car: 'ford', animal: 'dog' }

console.log(obj1);
// { food: 'pizza', car: 'ford' }

Here, {} is the new target object.

Using spread syntax

Modern JavaScript often uses spread syntax because it is short and readable:

const obj1 = { food: 'pizza', car: 'ford' };
const obj2 = { animal: 'dog' };

const merged = { ...obj1, ...obj2 };

console.log(merged);
// { food: 'pizza', car: 'ford', animal: 'dog' }

What if both objects have the same property?

const obj1 = { food: 'pizza', car: 'ford' };
const obj2 = { car: 'tesla', animal: 'dog' };

const merged = { ...obj1, ...obj2 };

console.log(merged);
// { food: 'pizza', car: 'tesla', animal: 'dog' }

The later object wins. Since obj2 comes after obj1, its car value replaces the old one.

Step by Step Execution

Consider this example:

const obj1 = { food: 'pizza', car: 'ford' };
const obj2 = { animal: 'dog' };

const merged = Object.assign({}, obj1, obj2);

Step by step:

  1. const obj1 = ...

    • JavaScript creates an object with two properties:
    • food: 'pizza'
    • car: 'ford'
  2. const obj2 = ...

    • JavaScript creates another object with one property:
    • animal: 'dog'
  3. Object.assign({}, obj1, obj2)

    • JavaScript starts with an empty object {}
    • It copies properties from obj1 into it
    • The object becomes:
    { food: 'pizza', car: 'ford' }
    
    • Then it copies properties from obj2
    • The object becomes:
    { food: 'pizza', car: 'ford', animal: 'dog' }
    
  4. merged now refers to the final combined object

Another trace with a conflict:

const a = { x: 1, y: 2 };
const b = { y: 99, z: 3 };
const result = { ...a, ...b };

Execution:

  1. Copy x: 1, y: 2 from a
  2. Copy y: 99, z: 3 from b
  3. y already exists, so 99 replaces 2
  4. Final result:
{ x: 1, y: 99, z: 3 }

Real World Use Cases

1. Default settings plus user settings

const defaults = { theme: 'light', notifications: true };
const userSettings = { theme: 'dark' };

const settings = { ...defaults, ...userSettings };

This keeps default values but lets user choices override them.

2. Building API request options

const baseOptions = { method: 'GET', headers: { Accept: 'application/json' } };
const authOptions = { token: 'abc123' };

const options = { ...baseOptions, ...authOptions };

This is common when preparing request objects.

3. Updating state in frontend apps

const state = { loading: true, data: null };
const nextState = { ...state, loading: false, data: [1, 2, 3] };

This is common in React and other UI libraries where new objects are preferred over mutation.

4. Combining form data

const basicInfo = { name: 'Ava', age: 25 };
const contactInfo = { email: 'ava@example.com' };

const formData = { ...basicInfo, ...contactInfo };

This helps gather related values before saving or sending them.

Take Quiz

Real Codebase Usage

In real projects, developers usually merge objects in a few standard ways.

Merging defaults with overrides

const defaultConfig = {
  timeout: 5000,
  retries: 2
};

function createConfig(customConfig) {
  return { ...defaultConfig, ...customConfig };
}

This pattern is everywhere in libraries and application setup.

Using immutable updates

Instead of changing an existing object, many codebases create a new one:

const updatedUser = { ...user, isAdmin: true };

This is safer in state management because it avoids accidental side effects.

Guarding against missing values

Developers often check that inputs are objects before merging:

function mergeFlatObjects(a, b) {
  if (!a || typeof a !== 'object') return b;
  if (!b || typeof b !== 'object') return a;
  return { ...a, ...b };
}

This is a simple guard clause pattern.

Overriding only selected properties

const request = {
  ...baseRequest,
  method: 'POST'
};

This copies all shared values and then changes only what is needed.

Validation before merging

When merging user input, codebases often validate keys or values first to avoid unexpected data entering the system.

Common Mistakes

1. Expecting a custom .merge() method to exist

This will not work on normal JavaScript objects:

const obj1 = { food: 'pizza' };
const obj2 = { animal: 'dog' };

obj1.merge(obj2); // Error

Plain objects do not have a built-in .merge() method.

Use:

Object.assign(obj1, obj2);

or:

const merged = { ...obj1, ...obj2 };

2. Forgetting that Object.assign() can mutate the target

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

Object.assign(obj1, obj2);
console.log(obj1); // changed

If you want a new object, use:

const merged = Object.assign({}, obj1, obj2);

3. Not understanding overwrite order

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

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

The later source wins.

4. Assuming this is a deep merge

const a = { settings: { darkMode: false } };
const b = { settings: { fontSize: 18 } };

const merged = { ...a, ...b };
console.log(merged);
// { settings: { fontSize: 18 } }

The nested settings object is replaced, not combined deeply.

5. Mutating objects when immutability is expected

In frameworks and shared code, changing the original object can cause bugs.

Prefer:

const newObject = { ...oldObject, updated: true };

when you want safer updates.

Comparisons

ApproachMutates original?Creates new object?Common useNotes
Object.assign(obj1, obj2)YesNoDirectly add properties to an existing objectGood when mutation is acceptable
Object.assign({}, obj1, obj2)NoYesMerge into a fresh objectClear and widely supported
{ ...obj1, ...obj2 }NoYesModern JavaScript mergingShort and readable

Object.assign() vs spread syntax

  • Object.assign() is older and explicit
  • Spread syntax is newer and often easier to read
  • Both perform shallow copies for plain object merging

Mutating vs non-mutating merge

StyleExampleWhen to use
MutatingObject.assign(target, source)When you intentionally want to update the existing object
Non-mutating{ ...target, ...source }When you want safer, predictable code

In modern code, non-mutating merges are usually preferred unless there is a specific reason to update the original object.

Take Quiz

Cheat Sheet

// Mutate obj1 by copying obj2 into it
Object.assign(obj1, obj2);

// Create a new merged object
const merged = Object.assign({}, obj1, obj2);

// Modern syntax for a new merged object
const merged = { ...obj1, ...obj2 };

Rules to remember

  • Objects are merged by copying top-level properties
  • If keys conflict, the later object wins
  • Object.assign(target, source) changes target
  • Spread syntax usually creates a new object
  • Both are shallow merges, not deep merges

Conflict example

const a = { x: 1 };
const b = { x: 2 };
const c = { ...a, ...b };
// c.x is 2

Safe default pattern

const options = { ...defaultOptions, ...userOptions };

Important edge case

Nested objects are not deeply merged:

const a = { config: { debug: true } };
const b = { config: { port: 3000 } };
const c = { ...a, ...b };
// c.config is { port: 3000 }

FAQ

Is there a built-in merge method on JavaScript objects?

No. Plain JavaScript objects do not have a .merge() method. Use Object.assign() or object spread syntax instead.

What is the easiest way to merge two objects in JavaScript?

For modern JavaScript, the most common approach is:

const merged = { ...obj1, ...obj2 };

Does Object.assign() change the original object?

Yes, it changes the target object you pass in as the first argument.

Which value wins if both objects have the same key?

The value from the later object wins.

Is object spread the same as deep merge?

No. It only copies top-level properties.

Should I use Object.assign() or spread syntax?

Use spread syntax for readability in modern code. Use Object.assign() if you specifically want to mutate an existing target or need that style for compatibility.

Can I merge more than two objects?

Yes.

const result = { ...a, ...b, ...c };

or:

Object.assign({}, a, b, c);
Take Quiz

Mini Project

Description

Build a small settings merger for a JavaScript app. The app has default settings, and a user can provide their own overrides. You will combine both objects into one final configuration object. This demonstrates one of the most common real-world uses of object merging.

Goal

Create a function that merges default settings with user-provided settings and returns the final result without changing the original defaults.

Requirements

  1. Create a defaultSettings object with at least three properties.
  2. Create a userSettings object that overrides at least one property and adds one new property.
  3. Write a function that returns a new merged object.
  4. Do not mutate the original defaultSettings object.
  5. Print the merged result and the original defaults to verify the behavior.
Take Quiz

Keep learning

Related questions

View more