Loading...
Loading...
How objects inherit from other objects. The foundation of JavaScript OOP.
Module 6 · How JavaScript Works
Understanding the engine makes you a better debugger. Execution contexts, the call stack, hoisting, memory allocation, closures, and the prototype chain explain why JavaScript behaves the way it does under the hood.
Every JavaScript object inherits from another object through the prototype chain — the mechanism behind shared methods, Object.create, and how classes actually work under the hood.
JavaScript looks simple on the surface, but the engine does a lot of work behind the scenes. Variables are hoisted, functions create new execution contexts, the call stack tracks nested calls, and the prototype chain resolves property lookups.
This module is for developers who want to stop guessing and start understanding. Visual diagrams of the call stack, heap, and scope chain make abstract concepts concrete — and directly improve your debugging skills in real projects.
Classes are syntactic sugar over prototypes. Array.map exists because arrays inherit from Array.prototype. Understanding prototypes demystifies built-ins, instanceof, and what class extends really does.
Every object has a hidden link to another object it inherits from.
const dog = { bark() { return "Woof!"; } }; const myDog = Object.create(dog); myDog.name = "Rex"; myDog.name; // "Rex" (own property) myDog.bark(); // "Woof!" (inherited from dog!) // myDog doesn't have bark() itself // but it has a PROTOTYPE LINK to dog // JavaScript follows the link to find bark()
myDog
name: "Rex"
dog
bark: ƒ
Object.prototype
toString, etc.
Two different things with confusing names.
__proto__ (or [[Prototype]])
.prototype (property)
function Person(name) { this.name = name; } Person.prototype.greet = function() { return "Hi, I'm " + this.name; }; const alice = new Person("Alice"); // alice.__proto__ === Person.prototype → true! // Person.prototype is the TEMPLATE // alice.__proto__ is the LINK to that template
Create an object with a specific prototype.
// Object.create(proto) — clean prototype inheritance: const animal = { alive: true, eat() { return "eating"; }, }; const cat = Object.create(animal); cat.name = "Whiskers"; cat.meow = function() { return "Meow!"; }; cat.name; // "Whiskers" (own) cat.meow(); // "Meow!" (own) cat.eat(); // "eating" (inherited from animal) cat.alive; // true (inherited) // Object.create(null) — no prototype at all: const bare = Object.create(null); bare.toString; // undefined (no Object.prototype!)
The pre-class way to create objects with shared methods.
function Car(make, model) { // 'new' creates an empty object and sets 'this' this.make = make; this.model = model; } // Shared methods go on .prototype: Car.prototype.describe = function() { return `${this.make} ${this.model}`; }; const tesla = new Car("Tesla", "Model 3"); tesla.describe(); // "Tesla Model 3"
Constructor functions + 'new' create objects. Methods on .prototype are shared (not copied) between all instances.
How JavaScript searches for a property.
const parent = { x: 1, y: 2 }; const child = Object.create(parent); child.z = 3; // Lookup for child.z: // 1. Check child itself → found! z = 3 ✓ // Lookup for child.x: // 1. Check child itself → not found // 2. Check child.__proto__ (parent) → found! x = 1 ✓ // Lookup for child.toString: // 1. Check child → not found // 2. Check parent → not found // 3. Check Object.prototype → found! ✓ // Lookup for child.foo: // 1. child → ✗ 2. parent → ✗ 3. Object.prototype → ✗ // 4. null (end of chain) → undefined
Key points:
hasOwnProperty() checks only own, not inheritedin operator checks both own and inheritedCommon questions about prototypes.