# Prototypes — Part 1: The Mechanism

## 1. What a Prototype Is

Every JavaScript object has an internal link to another object called its **prototype**. When you access a property that doesn't exist directly on an object, the engine automatically looks it up on the prototype — and if it's not there either, on the prototype's prototype, and so on.

```js
const animal = {
  eats: true,
  describe() { return "I am an animal"; },
};

const dog = Object.create(animal); // dog's prototype = animal
dog.barks = true;

console.log(dog.eats);       // true — found on the prototype
console.log(dog.describe()); // "I am an animal" — inherited method
console.log(dog.barks);      // true — own property
```

`dog` doesn't have `eats` or `describe` as its own properties — `Object.create(animal)` sets `animal` as `dog`'s prototype, and lookups fall through to it.

## 2. `__proto__` vs `prototype` — Two Different Things

This is the single most confusing naming collision in JavaScript:

| Name | What it is | Exists on |
|---|---|---|
| `obj.__proto__` (or `Object.getPrototypeOf(obj)`) | The **actual link** to the object's prototype | every object |
| `Fn.prototype` | The object that becomes the prototype of instances **created with `new Fn()`** | every function |

```js
function Dog(name) { this.name = name; }
Dog.prototype.bark = function () { return `${this.name} says woof`; };

const rex = new Dog("Rex");
console.log(rex.__proto__ === Dog.prototype); // true
console.log(rex.bark());                       // "Rex says woof"
```

`Dog.prototype` is a plain object. `new Dog(...)` creates a new object whose `__proto__` points at `Dog.prototype`. That's the entire mechanism behind "constructor functions."

![rex.__proto__ points at Dog.prototype, which is a separate object from the Dog function itself](diagrams/01-proto-vs-prototype.svg)

## 3. Own Properties vs Inherited Properties

```js
console.log(rex.hasOwnProperty("name")); // true — set in the constructor
console.log(rex.hasOwnProperty("bark")); // false — inherited via the prototype
console.log("bark" in rex);              // true — `in` checks the whole chain
```

`for...in` loops over both own and inherited enumerable properties, which is a common source of bugs — prefer `Object.keys(obj)` (own, enumerable only) when you just want the object's own data.

## 4. Setting a Prototype Property Never Mutates the Prototype

```js
dog.eats = false; // creates a NEW own property on dog
console.log(dog.eats);       // false
console.log(animal.eats);    // true — untouched
```

Assignment always creates/updates an **own** property; it never writes through to the prototype. Only reading falls through the chain — writing does not.

## 5. `Object.create` vs Constructor Functions vs `class`

All three ultimately do the same thing — link one object's prototype to another:

```js
// 1. Object.create — direct, explicit
const catA = Object.create(animal);

// 2. Constructor function — prototype set via Fn.prototype
function Cat() {}
Cat.prototype = animal;
const catB = new Cat();

// 3. class — syntactic sugar over the same mechanism
class Bird {}
Object.setPrototypeOf(Bird.prototype, animal);
const catC = new Bird();
```

`class` (covered in its own topic) is the modern, readable way to do this — but it compiles down to exactly this prototype machinery.

## 6. Under the Hood: Hidden Classes and Inline Caches

If every `obj.property` access literally walked the prototype chain object-by-object every single time, property access would be far too slow for real-world code. Engines avoid this with two cooperating optimizations.

### Hidden classes: giving objects a "shape"

V8 (and equivalent engines) assign every object an internal **hidden class** (sometimes called a "shape" or "structure") describing its layout: which properties it has, in which order, at which memory offsets. Two objects created the same way, with properties added in the same order, share the same hidden class:

```js
function Point(x, y) { this.x = x; this.y = y; }
const p1 = new Point(1, 2);
const p2 = new Point(3, 4);
// p1 and p2 share the SAME hidden class — both have {x, y} added in the same order
```

Adding a property transitions an object from one hidden class to another, forming a **transition tree** — this is precisely why constructor functions (and `class`, see the Classes topic) that always initialize the same fields in the same order are fast: every instance follows the identical transition path and ends up sharing hidden classes, instead of each object growing its own unique, unshared layout.

```js
const p3 = new Point(5, 6);
p3.z = 7; // p3 now transitions to a DIFFERENT hidden class than p1/p2 — it has an extra property
```

### Inline caches: remembering where a property was found last time

At each call site that reads a property (e.g. one specific `obj.eats` expression in your code), the engine keeps an **inline cache (IC)** that remembers: "the last time I saw an object with hidden class X here, the property was at offset N." The next time that same call site runs, if the incoming object has the *same* hidden class, the engine skips the prototype-chain walk entirely and jumps straight to that remembered offset.

| IC state | Meaning | Speed |
|---|---|---|
| **Monomorphic** | this call site has only ever seen ONE hidden class | fastest — direct offset read, no chain walk |
| **Polymorphic** | it's seen a handful (2-4) of different hidden classes | still fast — small lookup table of cached offsets |
| **Megamorphic** | it's seen many different hidden classes | falls back to a slower, generic property lookup — the chain-walking algorithm from the Prototype Chain topic runs for real again |

This is a direct, practical consequence of everything in sections 1-5: `dog.eats` looks like a single operation, but its *actual* speed depends heavily on whether the objects flowing through that line of code consistently share a hidden class — which in turn depends on using consistent constructors/classes rather than ad-hoc, differently-shaped object literals.

Continue to `js_prototypes_theory_2.md` for performance and shared-method patterns.
