5.5 — Prototypes
A confession: lesson 4.4's property-lookup story was incomplete. "Reading a missing key gives undefined" — mostly true, but then how does rabbit.toString() work when you never wrote a toString? How does every array know .push? You've been using inherited properties since lesson 0.3 without the machinery ever being named.
The machinery: every object carries one hidden link to another object — its prototype. The REAL lookup rule: check the object; on a miss, climb the link and check there; repeat until found or the chain ends. It's 5.3's rope-walk, but for object properties.
And it's how JavaScript shares one method among a million objects without copying it once.
const animal = {
eats: true,
sleep() {
return "zzz";
},
};
const rabbit = Object.create(animal);
rabbit.hops = true;
console.log(rabbit.hops);
console.log(rabbit.eats);
console.log(rabbit.color);
console.log(rabbit.sleep());
console.log(Object.keys(rabbit));Object.create(animal) builds a NEW, empty object whose hidden link — written [[Prototype]] in the spec — points at animal. Note what did NOT happen: nothing was copied. rabbit owns nothing yet except what we add next (hops). One arrow in the diagram, that’s the entire setup.
The deeper story, with the real names for things — this part is what turns “I saw it” into “I can explain it.”
Naming, precisely — interviewers probe this. The hidden link on every object is [[Prototype]], readable with Object.getPrototypeOf(obj). You'll also meet __proto__ — a legacy accessor for the same link; fine in DevTools, avoided in code.
Confusingly, functions also have a normal property literally named prototype — that's a different thing: it's the object that new will install as [[Prototype]] on instances. Next lesson makes that click.
Writing never climbs: rabbit.eats = false creates an OWN eats on rabbit that shadows animal's — animal is untouched, and other objects linked to animal still see true. Read-climbs, write-local is why one shared prototype is safe for a million instances.
And the memory math that motivates everything: methods on the instance = one function object per instance (a thousand rabbits, a thousand sleeps). Methods on the prototype = one function, ever.
That's the entire reason this system exists — and exactly what class automates next lesson.
⌨️ one recipe, many kitchens
Prove sharing with your own chain: one describe method living on a base object, borrowed by two different objects through their prototype links — with this doing its 5.4 job.
requirements:
- A base object
kitchenwith ONE method:describe(), returningthis.dish + " ready". - Two objects created WITH
kitchenas their prototype:pasta(own propertydish="pasta") andsoup(dish="soup"). Print each one'sdescribe(). - Prove the link: print whether
soup's prototype iskitchen(there's a built-in that answers this).
when you press RUN, the console must show exactly:
✏️ Quick check 1
Type exactly what this prints:
const base = { kind: "tool" };
const hammer = Object.create(base);
hammer.weight = 2;
console.log(hammer.kind);✏️ Quick check 2
Same setup — type exactly what THIS prints:
const base = { kind: "tool" };
const hammer = Object.create(base);
hammer.weight = 2;
console.log(Object.keys(hammer).length);✏️ Quick check 3
Every plain object’s chain ends at Object.prototype, whose own link points to ___. Type it.
🗣️ Now teach it back
Explain to a friend how rabbit.sleep() can work when rabbit has no sleep — the hidden link, the full lookup rule, where every chain ends, and why sharing methods this way saves memory.
Write it as if your friend is sitting next to you. Saved to your journal — future-you will use these notes to teach others.