JS Sketchbooksee JavaScript think ✏️
← back to phase 4

4.7 — Copying & equality

Lesson 4.6 left a warning on the table: copying a variable copies the arrow, so “copies” of objects aren't copies at all. Today we make real copies — and immediately discover that the most popular copying tool, spread (...), only copies one layer deep. Everything nested keeps being shared, and knowing exactly where the sharing starts is the difference between a settings screen with a working “cancel” button and one that corrupts the original.

Along the way, 4.6's other loose end gets tied: why {} === {} is false, and what === really asks when both sides are objects.

watch it happen
const base = { theme: "dark", flags: { beta: true } };

const copy = { ...base };
console.log(copy === base);

copy.theme = "light";
console.log(base.theme);

copy.flags.beta = false;
console.log(base.flags.beta);

The setup is two levels deep: base’s slot points at an object — and that object’s flags property holds an ARROW of its own, pointing at a second, inner object. Real data looks like this everywhere: objects holding objects holding arrays.

stackbasebase’s objecttheme: "dark"flags: ➝the ONE flags objectbeta: truetwo levels: base ➝ object, whose flags property ➝ anotherobjectconsole(nothing printed yet)
under the hood

The deeper story, with the real names for things — this part is what turns “I saw it” into “I can explain it.”

=== on objects answers one question: same address? It never looks inside. Two objects with identical contents are still !== — and there's no built-in “same contents” operator in the language.

(Test libraries add one: expect(a).toEqual(b) unpacks structure — a Phase 10 tool built entirely on today's idea.)

Spread ({ ...obj }, [...arr]) and Object.assign all make shallow copies. One new top-level container; each property copied slot-by-slot. So nested objects and arrays come along as shared arrows. A shallow copy is exactly right when the object is flat, and exactly one layer short when it isn't.

The real deep copy is structuredClone(value) — a modern built-in that rebuilds every layer.

You'll still meet the old home remedy JSON.parse(JSON.stringify(x)) in older code. It mostly works — but it silently drops undefined and functions, and damages dates. Knowing why takes exactly the JSON knowledge arriving in lesson 4.13.

your turn

⌨️ the copy that can keep a secret

A settings screen edits a DRAFT so cancel is possible — the original must survive anything the draft does. Prove where spread protects you, where it betrays you, and how to copy for real.

requirements:

  • Create profile: user = "vas", and prefs holding an object with sound = true.
  • Make a spread copy named draft. Change the draft's user to "guest", then print profile.user — the top layer must be safe.
  • Now make a FULL copy named clone where no layer is shared (JavaScript has a built-in for this). Set the clone's prefs.sound to false, then print profile.prefs.sound — the original must be untouched.
  • Finish by printing clone === profile.

when you press RUN, the console must show exactly:

vas
true
false

✏️ Quick check 1

Type exactly what this prints:

const a = { n: 1 };
const b = { n: 1 };
console.log(a === b);

✏️ Quick check 2

Type exactly what this prints:

const p = { name: "Ida", tags: ["new"] };
const q = { ...p };
q.tags.push("vip");
console.log(p.tags.length);

✏️ Quick check 3

Type exactly what this prints:

const x = { k: 1 };
const y = { ...x };
y.k = 9;
console.log(x.k);
teach it back

🗣️ Now teach it back

A friend spread-copied their settings object, edited the copy’s nested prefs, and corrupted the original anyway. Explain why the top level was safe but the nested part wasn’t — and what tool makes a copy with nothing shared.

Write it as if your friend is sitting next to you. Saved to your journal — future-you will use these notes to teach others.

a few sentences, minimum — you’ve got this
to remember
=== on objects compares ADDRESSES: identical contents are still !==, and {} === {} is false.
Spread / Object.assign copy ONE layer — properties holding arrows copy the arrow, so nested data stays shared (shallow copy).
structuredClone(value) copies every layer — the modern deep copy. (JSON round-trips are the old, lossy folk remedy.)
next: 4.8 Iterating collections →