ここからは、「クラスがどう内部で動いているか」=プロトタイプチェーンの裏側を、初心者でもイメージでつかめるように、図とアニメーション風の流れで解説します。
ステップ 1:クラスの正体とは?
実は JavaScript の「クラス」は、
「プロトタイプを使いやすくするための見た目」 です。
つまり中身は「関数+オブジェクト」の仕組みで動いています。
クラスを作ったときの裏側
class Person {
constructor(name) {
this.name = name;
}
greet() {
console.log(`こんにちは、私は${this.name}です`);
}
}
JavaScriptこれを JavaScript がどう処理しているかというと…
アニメーション①:クラス定義の裏側
あなた: class Person { ... } と書く
↓
JavaScriptの中ではこうなる!
↓
function Person(name) { this.name = name; }
Person.prototype.greet = function() {
console.log(`こんにちは、私は${this.name}です`);
};
JavaScriptつまりクラス構文は、「コンストラクター関数+プロトタイプのメソッド登録」を
裏でやってくれているだけなんです。
ステップ 2:インスタンスを作るときの流れ
const alice = new Person("Alice");
JavaScriptアニメーション②:インスタンス生成の流れ
new Person("Alice")
↓
① 新しいオブジェクトを作る
↓
② そのオブジェクトの __proto__ を
Person.prototype に設定する
↓
③ constructor を呼び出して
this.name = "Alice" をセット!
↓
インスタンス完成 🎉
JavaScript図で見る関係(プロトタイプチェーン)
┌───────────────────────────────┐
│ class Person │
│ constructor(name) {...} │
│ greet() {...} │
└──────────────┬────────────────┘
│
(prototype でつながる)
│
┌──────────────┴───────────────┐
│ Person.prototype │
│ { greet: f() } │
│ ↑ │
│ prototype → Object.prototype │
└──────────────┬───────────────┘
│
new Person("Alice")
↓
┌─────────────────────┐
│ alice オブジェクト │
│ { name: "Alice" } │
│ __proto__ → Person.prototype
└─────────────────────┘
JavaScript💡 alice からメソッドを呼ぶときの動き:
alice.greet()を探すalice自身にgreetがないalice.__proto__(つまりPerson.prototype)を探す- あった! →
greetを実行 🎯 - なければさらに上(
Object.prototype)へ探索が続く
ステップ 3:プロトタイプチェーン探索のアニメーション
alice.greet();
JavaScript探索アニメーション
alice ----> { name: "Alice" }
│
│(ここに greet ある?) ❌
│
▼
Person.prototype ----> { greet() }
│
│(ここに greet ある?) ✅ 見つけた!
│
▼
実行: console.log("こんにちは、私はAliceです")
JavaScriptもし greet が Person.prototype にもなければ…
▼
Object.prototype ----> { toString(), hasOwnProperty() ... }
│
│(ここに greet ある?) ❌
▼
undefined → TypeError: greet is not a function
JavaScriptテップ 4:継承したときの内部構造(extends)
class Student extends Person {
study() {
console.log(`${this.name}は勉強中です`);
}
}
const bob = new Student("Bob");
JavaScriptアニメーション③:継承の裏側
Student.prototype.__proto__ → Person.prototype
Student.__proto__ → Person
JavaScriptつまり「子クラスの prototype が親クラスの prototype を引き継ぐ」ようにつながります。
図で見る「継承チェーン」
┌───────────────┐
│ bob │
│ { name: "Bob"}│
│ __proto__ → Student.prototype
└───────────────┘
│
▼
┌───────────────────┐
│ Student.prototype │
│ { study() } │
│ __proto__ → Person.prototype
└───────────────────┘
│
▼
┌──────────────────┐
│ Person.prototype │
│ { greet() } │
│ __proto__ → Object.prototype
└──────────────────┘
JavaScript呼び出しアニメーション
bob.greet();
JavaScriptbob → Student.prototype → Person.prototype → Object.prototype
↑ ↑ ↑
(なし) (なし) ✅ greet 見つけた!
JavaScriptbob.study();
JavaScriptbob → Student.prototype → ✅ study 見つけた!
JavaScriptステップ 5:super の正体(中のしくみ)
class Student extends Person {
constructor(name, grade) {
super(name); // ← これが親の constructor を呼ぶ
this.grade = grade;
}
}
JavaScript実際は:
super(name)
↓
Person.call(this, name)
JavaScriptつまり、
「親クラスのコンストラクタを、今の this で呼んでる」
という動きなんです。
ステップ 6:全体構造まとめ(図解)
┌────────────────────────┐
│ Object.prototype │
│ toString(), ... │
└──────────┬─────────────┘
│
┌──────────┴─────────────┐
│ Person.prototype │
│ greet() │
└──────────┬─────────────┘
│
┌──────────┴─────────────┐
│ Student.prototype │
│ study() │
└──────────┬─────────────┘
│
┌──────────┴─────────────┐
│ bob (インスタンス) │
│ name: "Bob" │
└────────────────────────┘
JavaScript探索ルール:
👉 「自分 → 自分のプロトタイプ → その親のプロトタイプ → … → Object.prototype」
の順に探していく。
まとめ:クラスとプロトタイプの関係
| 見た目(クラス) | 実際の中身(プロトタイプ) |
|---|---|
class Person {} | function Person() {} と Person.prototype の組み合わせ |
extends | 子の prototype.__proto__ が親の prototype を指す |
super() | 親の constructor を this で呼ぶ |
| メソッド定義 | ClassName.prototype.メソッド名 = function() {} |
new Class() | 新しいオブジェクトを作り、__proto__ に Class.prototype をつなぐ |
