JavaScript の クラス (class) を初心者向けに、なるべくわかりやすく説明します。全体像 → 各パーツ → 例 → 注意点、という流れで進めます。
全体像:クラスって何?なぜ使う?
- JavaScript はもともと プロトタイプベース のオブジェクト指向言語で、「オブジェクトが別のオブジェクトを原型 (プロトタイプ) として参照して振る舞いを継承する」という仕組みがあります。
- クラス構文は、そのプロトタイプ継承の考え方を、Java や C++ のように見える形で書けるようにした “糖衣構文 (syntactic sugar)” の一つ、という見方ができます。
- クラスを使うと、「ある型(例えば「人間」「車」「色」など)」を定義し、その型に属する複数のインスタンス(実体)を簡単につくったり共通の処理をまとめたりできます。
例:class Person { … } と定義しておいて、new Person("Alice"), new Person("Bob") といった具合に複数の “人” を作る。
クラスの基本構成要素
以下がクラスを構成する主な要素です。
| 要素 | 説明 | 例 |
|---|---|---|
| クラス宣言 / クラス式 | class MyClass { … } で宣言する。式として変数に代入することも可能。 | class Color { … } または const C = class { … } |
| コンストラクター (constructor) | インスタンスを生成するとき(new したとき)最初に実行される初期化処理を書く。プロパティを this に代入することが多い。 | constructor(r, g, b) { this.r = r; this.g = g; this.b = b; } |
| インスタンスメソッド | 各インスタンス(オブジェクト)が利用できるメソッド。プロトタイプに配置され、各インスタンスで共有される。 | getRed() { return this.r; } |
| フィールド(プロパティ) | データを格納するための変数。パブリックフィールド と プライベートフィールド の方法がある。 | myField = "foo"; や #myPrivate = 123; |
| アクセサ (getter / setter) | プロパティに対して “まるで直接プロパティのように” 読み書きできるメソッドを書ける。 | get red() { return this.r; } や set red(v) { this.r = v; } |
| 静的メソッド / 静的プロパティ | インスタンスではなく「クラス自身」に属するメソッドやプロパティ。ユーティリティ的な機能などに使われる。 | static isValid(r,g,b) { … } |
| 継承 (extends / super) | あるクラスを拡張し、親クラスの機能を引き継ぎつつ新しい機能を追加できる。super(...) を使って親クラスの constructor を呼ぶ。 | class ColorWithAlpha extends Color { … } |
具体例で見てみよう:Color クラス
以下のようなクラスを考えてみます。
class Color {
// プライベートフィールド(インスタンス内部だけ使う)
#values;
constructor(r, g, b) {
// 初期化
this.#values = [r, g, b];
}
// インスタンスメソッド
getRed() {
return this.#values[0];
}
setRed(value) {
if (value < 0 || value > 255) {
throw new RangeError("Invalid R value");
}
this.#values[0] = value;
}
// アクセサ(プロパティ風に使える get / set)
get red() {
return this.#values[0];
}
set red(v) {
if (v < 0 || v > 255) {
throw new RangeError("Invalid R value");
}
this.#values[0] = v;
}
// 静的メソッド(クラス自身に属する)
static isValid(r, g, b) {
return [r, g, b].every(v => v >= 0 && v <= 255);
}
// 継承したクラスで toString を上書き(オーバーライド)できるような例
toString() {
return this.#values.join(", ");
}
}
JavaScriptこのクラスの使い方例:
const c = new Color(100, 150, 200);
console.log(c.getRed()); // 100
c.setRed(255);
console.log(c.red); // 255(アクセサを使っても OK)
console.log(Color.isValid(0, 128, 255)); // true
console.log(c.toString()); // "255, 150, 200"
JavaScriptポイント:
#valuesはプライベートなので、クラスの外からc.#valuesのようにアクセスするとエラーになる。get red/set redを使うと、c.red = 50;のような見た目で書けるが、裏でバリデーション(0〜255チェックなど)を行える。- 静的メソッド
isValidは、インスタンスを生成しなくてもColor.isValid(...)で使える。
継承(サブクラス)の例
Color クラスを拡張して、アルファ値(透明度)を持つクラスを作る例:
class ColorWithAlpha extends Color {
#alpha;
constructor(r, g, b, a = 1) {
// `super` を使って親クラス Color のコンストラクタを呼ぶ
super(r, g, b);
this.#alpha = a;
}
get alpha() {
return this.#alpha;
}
set alpha(v) {
if (v < 0 || v > 1) {
throw new RangeError("Alpha must be between 0 and 1");
}
this.#alpha = v;
}
toString() {
// 親クラスの toString を使いつつ、自分の alpha も追加
return `${super.toString()}, ${this.#alpha}`;
}
// 静的メソッドをオーバーライドする例
static isValid(r, g, b, a) {
return super.isValid(r, g, b) && a >= 0 && a <= 1;
}
}
JavaScriptこうすると、
const ca = new ColorWithAlpha(10, 20, 30, 0.5);
console.log(ca.red); // 10(Color のプロパティも使える)
console.log(ca.alpha); // 0.5
console.log(ca.toString()); // "10, 20, 30, 0.5"
console.log(ColorWithAlpha.isValid(255, 0, 0, 0.8)); // true
JavaScript注意点:
- 派生クラスのコンストラクタでは、
thisを使う前にsuper(...)を呼ぶ必要がある。 - 派生クラスでも静的メソッドやプロパティは継承されるが、オーバーライドや拡張が可能。
- 親クラスのプライベートフィールド (
#valuesなど) は、子クラス側から直接アクセスできない。
その他のポイント・注意点
- クラス宣言は 巻き上げ (hoisting) されない(宣言より前に使おうとするとエラーになる)ので、クラスを宣言する前に
new MyClass()などはできない。 newを使わずにクラスを呼び出すとエラーになる(クラスのコンストラクタはnew呼び出し必須)。- プロトタイプベースの継承を理解しておくと、クラスの背後でどう動いているかを理解しやすくなる(クラスはあくまで見かけを簡潔にする構文)。
- 過度な継承階層は複雑さを招くので注意(設計をシンプルに保つことが重要)。
