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.
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.
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.
⌨️ 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", andprefsholding an object withsound=true. - Make a spread copy named
draft. Change the draft'suserto"guest", then printprofile.user— the top layer must be safe. - Now make a FULL copy named
clonewhere no layer is shared (JavaScript has a built-in for this). Set the clone'sprefs.soundtofalse, then printprofile.prefs.sound— the original must be untouched. - Finish by printing
clone === profile.
when you press RUN, the console must show exactly:
✏️ 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);🗣️ 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.