Copying with spread
Spread ... inside an object literal copies the properties of another object.
const user = { name: "Maya", age: 28 };
const copy = { ...user };
copy.age = 29;
console.log(user.age); // → 28
console.log(copy.age); // → 29
Merging and overriding
Later properties win.
const defaults = { theme: "light", fontSize: 14, sidebar: true };
const preferences = { theme: "dark", fontSize: 18 };
const settings = { ...defaults, ...preferences };
console.log(settings);
// → { theme: dark, fontSize: 18, sidebar: true }
This “defaults then overrides” pattern is everywhere in real code.
Updating one property without mutating
const user = { name: "Maya", age: 28, city: "Pune" };
const older = { ...user, age: 29 };
console.log(older); // → { name: Maya, age: 29, city: Pune }
console.log(user.age); // → 28
Frameworks like React rely on this pattern: create a new object rather than changing the old one.
Removing a property
const user = { name: "Maya", password: "secret", age: 28 };
const { password, ...safeUser } = user;
console.log(safeUser); // → { name: Maya, age: 28 }
Object.assign
Object.assign(target, ...sources) copies properties into the target object, changing it, and returns it.
const target = { a: 1 };
const result = Object.assign(target, { b: 2 }, { c: 3 });
console.log(target); // → { a: 1, b: 2, c: 3 } (mutated)
console.log(result === target); // → true
const merged = Object.assign({}, { a: 1 }, { b: 2 }); // to avoid mutating, start with {}
console.log(merged); // → { a: 1, b: 2 }
Spread is shorter and clearer for new code. Object.assign is common in older code, and it is useful when you do want to change an existing object.
Shallow, not deep
Both only copy the top level. Nested objects are still shared.
const a = { profile: { age: 28 } };
const b = { ...a };
b.profile.age = 99;
console.log(a.profile.age); // → 99
For a real independent copy, see Copying Objects.