Objects and destructuring
Property shorthand, spread merging, optional chaining, and copying objects without the reference traps.
Short modern syntax
const id = 7, active = true;
const user = { id, active }; // property shorthand
const user2 = { id, role: 'admin', login() { return this.id; } };
const { id: userId, role = 'guest' } = user2; // rename + default
const copy = { ...user2, role: 'owner' }; // spread override- Computed keys:
{ [key]: value }. - Optional chaining:
user?.profile?.emailβ short-circuits instead of throwing. - Nullish coalescing:
x ?? 'default'β unlike||it keeps0and''.
References and copies
Objects are copied by reference: assigning one does not clone it, so both variables point at the same data.
const a = { tags: ['x'] };
const b = a;
b.tags.push('y');
console.log(a.tags); // ['x','y'] - same object
const shallow = { ...a }; // top level copied only
const deep = structuredClone(a); // true deep copy (modern runtimes)β οΈ
Spread is a shallow copy β nested objects still share references. Use
structuredClone for a genuine deep copy (it handles Dates, Maps and Sets; unlike JSON.parse(JSON.stringify()), which silently mangles them).Object vs Map
| Use | When |
|---|---|
| Object | Fixed known shape, JSON interchange, simple records |
| Map | Dynamic keys, frequent add/remove, non-string keys, insertion order matters |
const m = new Map();
m.set(user, 'cached'); // any key type
m.size; // no Object.keys length dance
for (const [k, v] of m) console.log(k, v);FAQ
How do I safely read a nested value?
Optional chaining plus nullish coalescing:
cfg?.db?.host ?? 'localhost'.Why does mutating the copy change the original?
You copied the reference, not the data. Use spread for one level or
structuredClone for the whole tree.Related
Last refreshed 2026-09-17.