概要
JavaScriptではオブジェクトを定義する方法が複数あり、それぞれ使いどころが異なります。主に以下の3種類がよく使われます:
- オブジェクトリテラル(Object Literal)
- コンストラクタ関数(Constructor Function)
- クラス構文(Class Syntax, ES6以降)
これらは見た目だけでなく、内部的な動きや設計思想も異なります。用途に応じて使い分けることが重要です。
目次
オブジェクトリテラル
定義例
const user = {
name: "Alice",
age: 25,
greet() {
console.log(`Hello, I'm ${this.name}`);
}
};
user.greet(); // Hello, I'm Alice
-
{ ... }
という記法で即座にオブジェクトを作成する方法。 - プロパティ(キー:値ペア)とメソッドを含められる。
-
this
を使ったメソッドは、呼び出し時にオブジェクト自身を指します(“ドットの前のオブジェクト”)。 ([javascript.info][1]) - JavaScript.info によれば、オブジェクトはこのリテラル記法が基本形とされており、プロパティの操作(追加・削除・参照)も簡単にできると説明されています。 ([javascript.info][2])
長所・短所
長所 | 短所 |
---|---|
書きやすく、すぐにオブジェクトを定義できる | 同様の構造を持つオブジェクトを繰り返し作るには不便 |
小さな設定オブジェクト・データ表現に向く | メソッドを多数持たせたり継承を扱いたい場合には冗長になる |
コンストラクタ関数
JavaScriptでは、関数を使って 設計図(型) を定義し、new
を使ってインスタンスを生成する方法があります。これは伝統的なオブジェクト指向スタイルです。
定義例
function User(name, age) {
this.name = name;
this.age = age;
}
User.prototype.greet = function() {
console.log(`Hi, I'm ${this.name}`);
};
const alice = new User("Alice", 25);
alice.greet(); // Hi, I'm Alice
-
User
関数内でthis
にプロパティを設定する。 - メソッドは
User.prototype
に定義することで、複数インスタンス間で共有可能。 -
new User(...)
を行うと、空オブジェクトが生成され、this
に紐づけられ、コンストラクタ関数の処理が実行され、最後にそのオブジェクトが返されます。 ([javascript.info][3]) - JavaScript.info の “Constructor, operator new” 解説では、この手法で似た構造を持つオブジェクトを多く生成できる旨が説明されています。 ([javascript.info][3])
長所・短所
長所 | 短所 |
---|---|
多くのインスタンスを生成できる | プロトタイプの理解が必要 |
メソッドを共有することでメモリ効率が良い | 書く量が増える・初学者には理解しにくい |
クラス構文(ES6)
ES6以降、JavaScriptには class
キーワードが導入され、上記のコンストラクタ関数 + プロトタイプをより分かりやすく書くことができる構文が提供されました。
定義例
class User {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
console.log(`Hello, I'm ${this.name}`);
}
}
const bob = new User("Bob", 30);
bob.greet(); // Hello, I'm Bob
-
constructor
メソッドでインスタンスの初期化を行う。 ([javascript.info][4]) - クラスメソッド(
greet
など)はUser.prototype
に定義されるので、インスタンス間で共有される。 ([javascript.info][4]) -
class
構文は「糖衣構文(syntactic sugar)」であり、背後では従来の関数 & プロトタイプの仕組みが動作しています。 ([javascript.info][4])
長所・短所
長所 | 短所 |
---|---|
コードが読みやすく、オブジェクト指向スタイルに近い | 内部仕組み(プロトタイプなど)を理解していないと混乱する可能性 |
継承、getter/setter、クラスフィールドなどの機能が使いやすい | 古い環境ではポリフィルが必要になることもある |
比較と使い分け
特性 | オブジェクトリテラル | コンストラクタ関数 | クラス構文 |
---|---|---|---|
定義の簡潔さ | 非常に簡単 | 少し冗長 | 比較的簡潔 |
インスタンス生成 | 1つ | 複数可能 | 複数可能 |
メソッド共有 | 各オブジェクトごとに定義 | プロトタイプで共有可能 | クラスプロトタイプで共有 |
継承・拡張 | 手動で設定が必要 | プロトタイプ継承 |
extends による継承が使いやすい |
推奨場面 | 設定オブジェクト、小規模データ | 多数インスタンス + メソッドが必要な場合 | 現代的な設計・可読性重視の場面 |
ユースケース例
1. 設定オブジェクトなど単発用途
const config = { apiUrl: "https://api.example.com", timeout: 5000 };
2. 多くのユーザーを扱う Web アプリ
class User {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
console.log(`Hi, ${this.name}`);
}
}
const u1 = new User("Alice", 25);
const u2 = new User("Bob", 30);
u1.greet();
u2.greet();
3. カスタムオブジェクト生成の柔軟性が必要な場合
function Car(make, model) {
this.make = make;
this.model = model;
}
Car.prototype.info = function() {
console.log(`${this.make} ${this.model}`);
};
const c1 = new Car("Toyota", "Corolla");
c1.info();