Skip to content

Object.assign

This lesson explains Object.assign with clear examples, use cases, and best practices so you can use modern JavaScript confidently in real projects.

ES6+ Object.assign Overview

Object.assign() copies enumerable own properties from one or more source objects into a target object. It is commonly used to merge objects, clone objects, and update state in modern JavaScript applications.

Although the object spread operator is now widely used, Object.assign() remains important because it mutates the target object and is still common in older codebases and certain utility patterns.

Feature Description
Introduced In ES6 (ECMAScript 2015)
Syntax Object.assign(target, ...sources)
Behavior Copies properties into the target object
Return Value The modified target object
Copy Type Shallow copy
Common Uses Merging, cloning, defaults, state updates

Basic Object.assign Example

const target = {
  name: "Alex"
};

const source = {
  role: "admin",
  active: true
};

const result =
  Object.assign(
    target,
    source
  );

console.log(result);
console.log(target);

Properties from source are copied into target, and the same modified target object is returned.

How Object.assign Works

Object.assign() loops through each source object and copies its own enumerable properties into the target. If the same key exists in multiple sources, the later source wins.

Step Description Example
Choose Target Select the object to receive properties. const target = { }
Add Sources Pass one or more source objects. source1, source2
Copy Properties Enumerable own keys are copied. role: "admin"
Resolve Conflicts Later sources override earlier ones. theme: "dark"
Return Target Modified target is returned. result

Merge Multiple Objects

const defaults = {
  theme: "light",
  language: "en",
  notifications: false
};

const userPrefs = {
  theme: "dark"
};

const session = {
  notifications: true
};

const settings =
  Object.assign(
    {},
    defaults,
    userPrefs,
    session
  );

console.log(settings);

Passing an empty object as the target is a common way to merge multiple sources into a new object without mutating the originals.

Clone an Object

const original = {
  id: 1,
  name: "Sam",
  active: true
};

const copy =
  Object.assign({}, original);

copy.name = "Updated Name";

console.log(original.name);
console.log(copy.name);

Object.assign({}, obj) creates a shallow clone of the top-level properties in an object.

Update Object Properties

const user = {
  id: 10,
  name: "Alex",
  role: "viewer"
};

Object.assign(user, {
  role: "editor",
  lastLogin: "2026-06-27"
});

console.log(user);

You can update an existing object by using it as the target and passing new properties in a source object.

Later Sources Override Earlier Ones

const base = {
  status: "draft",
  theme: "light"
};

const overrideA = {
  theme: "dark"
};

const overrideB = {
  theme: "blue",
  status: "published"
};

const result =
  Object.assign(
    {},
    base,
    overrideA,
    overrideB
  );

console.log(result);

When multiple sources define the same property, the value from the last source is used.

Understand Shallow Copying

const original = {
  title: "Dashboard",
  settings: {
    theme: "light"
  }
};

const copy =
  Object.assign({}, original);

copy.settings.theme = "dark";

console.log(
  original.settings.theme
);
console.log(
  copy.settings.theme
);

Object.assign() performs a shallow copy. Nested objects are still shared by reference, so changing nested data affects both objects unless you clone deeper levels too.

Apply Default Values

function createProfile(
  options = {}
) {
  const defaults = {
    theme: "light",
    language: "en",
    notifications: true
  };

  return Object.assign(
    {},
    defaults,
    options
  );
}

const profile =
  createProfile({
    language: "fr"
  });

console.log(profile);

Default values are a common use case. User-provided options override defaults while missing keys keep their fallback values.

Object.assign vs Spread Operator

const base = {
  id: 1,
  name: "Alex"
};

const update = {
  role: "admin"
};

const withAssign =
  Object.assign(
    {},
    base,
    update
  );

const withSpread = {
  ...base,
  ...update
};

console.log(withAssign);
console.log(withSpread);
Feature Object.assign() Object Spread
Syntax Object.assign(target, source) { ...source }
Readability Function-based Often cleaner for merges
Mutation Can mutate target directly Creates new object literal
Common Use Utilities and legacy code Modern immutable updates

Common Object.assign Use Cases

  • Merging configuration and user preference objects.
  • Creating shallow clones of plain objects.
  • Updating existing objects with new properties.
  • Applying default options in utility functions.
  • Combining API response fragments.
  • Copying props in older React or Redux patterns.
  • Building objects from multiple dynamic sources.

Object.assign Best Practices

  • Use an empty object as the target when you want a new merged object.
  • Remember that Object.assign() performs a shallow copy.
  • Prefer spread syntax for simple immutable merges in modern code.
  • Place defaults first and overrides later.
  • Avoid mutating shared objects unintentionally.
  • Use deep cloning when nested objects must be independent.
  • Keep source object order intentional when keys may overlap.

Common Object.assign Mistakes

  • Mutating the original object when a clone was intended.
  • Expecting nested objects to be deeply copied.
  • Forgetting that later sources override earlier ones.
  • Passing null or undefined as the target.
  • Assuming inherited properties are copied.
  • Using Object.assign() for arrays when merge behavior is unexpected.
  • Overwriting important defaults by passing sources in the wrong order.

Key Takeaways

  • Object.assign() copies properties into a target object.
  • It returns the modified target object.
  • Later sources override earlier ones for duplicate keys.
  • It performs a shallow copy, not a deep clone.
  • Use it to merge, clone, and apply defaults in object-based workflows.

Pro Tip

To merge without mutating originals, use Object.assign({}, defaults, options) or the equivalent spread pattern { ...defaults, ...options }.