Object.assign()

Copies own enumerable properties from source objects onto a target object and returns it.

Signature
Object.assign(target, source1, source2, /* …, */ sourceN)
  • Added in JavaScript ES2015

Parameters

ParameterTypeDescription
$targetObjectThe target object to apply the sources' properties to. It is mutated and then returned. Primitives are converted to objects.
$source1, …, sourceNoptionalObjectOne or more source objects containing the properties to copy. null and undefined sources are ignored.

Return value

ObjectThe modified target object — the same reference that was passed in, not a new object.

Errors

Throws a TypeError if target is null or undefined, or if a property assignment fails — for example when the target property is non-writable or a setter on the target throws.

Object.assign() copies own enumerable properties — string keys and symbol keys — from each source onto the target, left to right, so later sources overwrite earlier ones. It mutates and returns the target rather than producing a new object; passing {} as the target is what makes it a copy.

When to reach for it

The two everyday uses are merging options over defaults, Object.assign({}, defaults, userOptions), and mutating an existing object in place, Object.assign(state, patch). Object spread ({ ...a, ...b }) covers the first case more readably; Object.assign() is still the right tool when the target must be an existing object you cannot replace.

What trips people up

The copy is shallow. Nested objects are copied by reference, so mutating copy.nested.x also changes original.nested.x. Use structuredClone() for a deep copy.

Getters on a source are invoked and their results copied as plain data properties — the accessor itself is not preserved. Setters on the target are invoked. And if an assignment throws partway through, the properties copied before the error stay on the target; there is no rollback.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Merge user-supplied options over a defaults object without mutating the defaults
  • Apply a patch to an existing state object that other code already holds a reference to
  • Collect several partial objects into one payload before sending it
  • Copy properties onto an instance inside a constructor

Frequently asked questions

Does Object.assign() deep copy nested objects?

No — it is a shallow copy, so nested objects are shared by reference between the source and the result; use structuredClone() when you need a deep copy.

What is the difference between Object.assign() and object spread?

Spread ({ ...a, ...b }) always creates a new object and defines properties directly, while Object.assign() mutates an existing target and triggers setters on it — so use spread for copies and Object.assign() when the target must stay the same reference.

Why is Object.assign() not copying some properties?

It only copies own enumerable properties; inherited properties and anything defined with enumerable: false are skipped.

More examples

Getters are flattened to values

The descriptor shows a plain writable data property with value 42 — the getter ran once during the copy and was not carried over.

Example · javascript
const source = {
  get computed() {
    return 6 * 7;
  },
};

const copy = Object.assign({}, source);
console.log(copy.computed);
console.log(Object.getOwnPropertyDescriptor(copy, "computed"));

Inherited and non-enumerable properties are skipped

Only { visible: 3 } is copied: the prototype property and the non-enumerable property are both excluded.

Example · javascript
const obj = Object.create(
  { fromProto: 1 },
  {
    hidden: { value: 2, enumerable: false },
    visible: { value: 3, enumerable: true },
  },
);

console.log(Object.assign({}, obj));

A failed assignment stops the copy

Prints 2 and undefined — the copy stopped at the non-writable property, keeping what it had already written and never reaching b.

Example · javascript
const target = Object.defineProperty({}, "locked", { value: 1, writable: false });

try {
  Object.assign(target, { a: 2 }, { locked: 3, b: 4 });
} catch (err) {
  console.log(err.constructor.name);
}

console.log(target.a, target.b);

Discussion

  • Be the first to comment on this lesson.