Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
Classes  ›  Capstone Project

Object Prototype and Prototypal Inheritance

Object Prototype 12 minEvery object has an internal [[Prototype]] link to another object; reading a missing property walks that chain — own property, then prototype, then its prototype, and so on — and class/extends syntax is built entirely on top of this same prototype chain.

Object Prototype and Prototypal Inheritance

In short: every object carries a hidden link, [[Prototype]], to another object. Reading a property that isn't on the object itself doesn't fail right away — JavaScript walks the [[Prototype]] chain, checking each linked object in turn, until it finds a match or runs out of chain. class and extends are not a separate system from this — they're syntax built entirely on top of it. A class's methods live on its .prototype object, and extends simply links one class's .prototype to point at its parent's, continuing the same chain.

![A chain of three shelves: d (instance, own: name = "Rex", no bark() here) → [[Prototype]] → Dog.prototype (bark(), found here, stop looking) → [[Prototype]] → Animal.prototype (speak()) — d.bark(): not own, check Dog.prototype, found, run it; d.speak(): not own, not on Dog.prototype, keep climbing to Animal.prototype, found — class syntax builds exactly this chain](/api/assets/javascript/assets/8ab365d058b468eb.png)

Confirm a class's methods live on .prototype, not the instance

A class instance's own properties come from the constructor; its methods are found one step up the [[Prototype]] chain, on the class's .prototype object:

javascript

Object.getPrototypeOf(s) === Song.prototype is true — that's the actual [[Prototype]] link. s.hasOwnProperty("describe") is false — describe was never copied onto s itself. Song.prototype.hasOwnProperty("describe") is true — that's where it actually lives. "describe" in s is still true, because in checks the whole chain, not just own properties.

Walk a two-level chain built by extends

extends links one class's .prototype to its parent's — a lookup that doesn't find something on the first shelf keeps climbing:

javascript

d's [[Prototype]] is Dog.prototype; Dog.prototype's own [[Prototype]] is Animal.prototype — a genuine chain, two links long. d.bark() finds bark on the first shelf, Dog.prototype. d.speak() isn't there, so the lookup keeps climbing to Animal.prototype, where it finds speak and runs it.

Build the same chain by hand, with Object.create

class/extends is convenient syntax for exactly this mechanism — the same chain can be built directly with Object.create:

javascript

Object.create(base) makes a new object whose [[Prototype]] is base directly — no class involved at all. child.greet() still works, found by walking up to base. child.hasOwnProperty("greet") is false — same result as the class example, because it's genuinely the same underlying mechanism.

Quick practice

quick drill

What does Object.getPrototypeOf(someInstance) === SomeClass.prototype tell you?

quick drill

Why does d.hasOwnProperty("bark") return false even though d.bark() works?

quick drill

In class Dog extends Animal, what does extends actually set up?

quick drill

What does Object.create(base) do?

quick drill

When a property lookup doesn't find a match on an object itself, what happens next?

🎯 Your turn

Given class Animal { speak() { return "..."; } } class Dog extends Animal { bark() { return "Woof"; } } const d = new Dog();, explain, in terms of [[Prototype]] and the lookup chain, exactly where d.bark() and d.speak() are found, and why d.hasOwnProperty("bark") is false even though d.bark() works fine.

Write your explanation and submit it — there's no code to run here, just your reasoning.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainWhere does bark() actually live?

Given class Animal { speak() { return "..."; } } class Dog extends Animal { bark() { return "Woof"; } } const d = new Dog();, explain, in terms of [[Prototype]] and the lookup chain, exactly where d.bark() and d.speak() are found, and why d.hasOwnProperty("bark") is false even though d.bark() works fine.