概要
JavaScriptにおけるオブジェクトリテラルとは、波括弧 {} を使用してキーと値のペアの集合を記述する構文である。
オブジェクトはJavaScriptの中心的なデータ構造であり、関連するデータや機能をひとまとまりとして表現する手段として広く使用される。
オブジェクトの各エントリはプロパティと呼ばれ、プロパティ名 (キー) と プロパティ値 (バリュー) で構成される。
プロパティの値には、文字列・数値・真偽値・配列・関数・別のオブジェクト等、あらゆるデータ型を指定できる。
値が関数である場合、そのプロパティはメソッドと呼ばれる。
プロパティへのアクセスには、ドット記法とブラケット記法の2種類がある。
ドット記法は読みやすくシンプルだが、変数やスペースを含むキーには対応していない。
ブラケット記法は柔軟性が高く、変数をキーとして使用できる。
ES2015 (ES6) では、算出プロパティ名やプロパティの短縮記法が導入され、オブジェクトリテラルをより簡潔に記述できるようになった。
また、Object.keys、Object.values、Object.entries 等の静的メソッドにより、プロパティの列挙や操作が容易になっている。
オブジェクトリテラルの基本
オブジェクトの作成
オブジェクトは波括弧 {} で囲んでプロパティを列挙することで作成する。
各プロパティは、キー: 値 の形式で記述し、カンマで区切る。
基本的なオブジェクトの作成例を以下に示す。
// シンプルなオブジェクト
const person = {
name: "Alice",
age: 30,
isActive: true
};
// プロパティの値として配列・関数・ネストしたオブジェクトを持つオブジェクト
const profile = {
name: "Alice",
age: 30,
hobbies: ["読書", "映画"],
address: {
city: "東京",
country: "日本"
},
greet: function() {
console.log("こんにちは、" + this.name);
}
};
// 空のオブジェクト
const empty = {};
プロパティ名には文字列として有効な任意の識別子を使用できる。
スペースやハイフンを含むプロパティ名を使用する場合は、引用符で囲む必要がある。
const obj = {
normalKey: "通常のキー",
"spaced key": "スペースを含むキー",
"hyphen-key": "ハイフンを含むキー",
123: "数値のキー (文字列として扱われる)"
};
プロパティとメソッド
オブジェクトのプロパティには任意のデータ型の値を格納できる。
値として関数を持つプロパティを特にメソッドと呼ぶ。
メソッド内では this キーワードを使用して、同一オブジェクトの他のプロパティにアクセスできる。
const person = {
name: "Alice",
age: 30,
hobbies: ["読書", "映画"],
greet: function() {
// thisはpersonオブジェクトを参照する
console.log("こんにちは、" + this.name);
},
getInfo: function() {
return this.name + " (" + this.age + "歳)";
}
};
person.greet(); // "こんにちは、Alice"
console.log(person.getInfo()); // "Alice (30歳)"
プロパティアクセス
ドット記法
ドット記法は、オブジェクト名の後にドット (.) を付け、続けてプロパティ名を記述する方法である。
シンプルで読みやすく、最も一般的に使用されるアクセス方法である。
const person = {
name: "Alice",
age: 30
};
console.log(person.name); // "Alice"
console.log(person.age); // 30
// ネストしたオブジェクトへのアクセス
const profile = {
address: {
city: "東京"
}
};
console.log(profile.address.city); // "東京"
存在しないプロパティにアクセスした場合は、undefined が返る。
const obj = { name: "Alice" };
console.log(obj.email); // undefined
ブラケット記法
ブラケット記法は、オブジェクト名の後に角括弧 [] を付け、その中にプロパティ名を文字列または変数で指定する方法である。
ドット記法では対応できないケースでブラケット記法を使用する。
const person = {
name: "Alice",
"favorite color": "blue",
1: "数値キー"
};
// 文字列でのアクセス
console.log(person["name"]); // "Alice"
// スペースを含むキーへのアクセス (ブラケット記法でしかアクセスできない)
console.log(person["favorite color"]); // "blue"
// 数値キーへのアクセス
console.log(person[1]); // "数値キー"
// 変数をキーとして使用する
const key = "name";
console.log(person[key]); // "Alice"
// 動的なキーへのアクセス
const fields = ["name", "age", "city"];
fields.forEach(function(field) {
console.log(field + ": " + person[field]);
});
ドット記法とブラケット記法の比較
下表に、ドット記法とブラケット記法の特性を比較する。
| 観点 | ドット記法 | ブラケット記法 |
|---|---|---|
| 構文 | obj.key |
obj["key"]
|
| 可読性 | 高い | やや低い |
| 変数をキーに使用 | 不可 | 可能 |
| スペースを含むキー | 不可 | 可能 |
| 数値で始まるキー | 不可 | 可能 |
| 予約語をキーに使用 | 不可 | 可能 |
プロパティ名が有効な識別子である場合は、可読性の高いドット記法を優先して使用することを推奨する。
変数・スペース・特殊文字を含むキーを扱う場合は、ブラケット記法を使用する。
プロパティの追加・変更・削除
オブジェクトは作成後もプロパティを動的に追加・変更・削除できる。
const obj = { a: 1, b: 2 };
// プロパティの追加
obj.c = 3;
obj["d"] = 4;
console.log(obj); // { a: 1, b: 2, c: 3, d: 4 }
// プロパティの変更
obj.a = 10;
obj["b"] = 20;
console.log(obj); // { a: 10, b: 20, c: 3, d: 4 }
// プロパティの削除
delete obj.c;
delete obj["d"];
console.log(obj); // { a: 10, b: 20 }
const で宣言したオブジェクトであっても、プロパティの追加・変更・削除は可能である。
const が禁止するのは、変数への再代入 (オブジェクト自体を別のオブジェクトに差し替えること) であり、オブジェクトの内容の変更ではない。
const obj = { name: "Alice" };
obj.name = "Bob"; // OK: プロパティの変更は可能
obj.age = 30; // OK: プロパティの追加も可能
// obj = { name: "Charlie" }; // エラー: constで宣言した変数への再代入は不可
オブジェクトの内容を完全に変更不可にする場合は、Object.freeze を使用する。
const frozen = Object.freeze({ name: "Alice", age: 30 });
frozen.name = "Bob"; // 変更が無視される (strict modeではエラー)
console.log(frozen.name); // "Alice" (変更されていない)
算出プロパティ名
ES2015で導入された算出プロパティ名 (Computed Property Names) は、プロパティ名をブラケット記法で動的に指定する構文である。
変数や式の評価結果をプロパティ名として使用できる。
基本的な使用例を以下に示す。
// 変数をプロパティ名に使用する
const key = "name";
const obj = { [key]: "Alice" };
console.log(obj); // { name: "Alice" }
console.log(obj.name); // "Alice"
// 式の評価結果をプロパティ名に使用する
const prefix = "user";
const obj2 = {
[prefix + "Name"]: "Alice",
[prefix + "Age"]: 30
};
console.log(obj2); // { userName: "Alice", userAge: 30 }
算出プロパティ名は、動的にプロパティ名を生成してオブジェクトを構築する時に有用である。
Reduxのreducerやフォームの状態管理等、実用的な場面で広く活用される。
// フォームの状態管理での活用例
function updateField(state, fieldName, value) {
return {
...state,
[fieldName]: value // 引数で受け取ったフィールド名をキーとして使用する
};
}
const formState = { name: "", email: "" };
const updated = updateField(formState, "name", "Alice");
console.log(updated); // { name: "Alice", email: "" }
プロパティの短縮記法
プロパティ名の短縮
ES2015で導入されたプロパティの短縮記法 (Property Shorthand) は、変数名とプロパティ名が同一の場合に、プロパティ名の記述を省略できる構文である。
// 従来の記法
const name = "Alice";
const age = 30;
const person = { name: name, age: age };
// 短縮記法 (変数名とプロパティ名が同じ場合は省略できる)
const personShort = { name, age };
console.log(personShort); // { name: "Alice", age: 30 }
関数の戻り値としてオブジェクトを返す場合にも短縮記法が活用される。
function createUser(name, age, email) {
// 変数名とプロパティ名が一致するため短縮記法を使用できる
return { name, age, email };
}
const user = createUser("Alice", 30, "alice@example.com");
console.log(user); // { name: "Alice", age: 30, email: "alice@example.com" }
メソッドの短縮記法
ES2015で導入されたメソッドの短縮記法は、オブジェクトのメソッドを function キーワード無しで記述できる構文である。
// 従来の記法
const obj = {
greet: function() {
console.log("Hello");
},
add: function(a, b) {
return a + b;
}
};
// 短縮記法
const objShort = {
greet() {
console.log("Hello");
},
add(a, b) {
return a + b;
}
};
objShort.greet(); // "Hello"
console.log(objShort.add(1, 2)); // 3
短縮記法のメソッドは通常の function キーワードで定義したメソッドと同等であり、this の参照も同様に機能する。
const person = {
name: "Alice",
// 短縮記法でもthisは正しく機能する
greet() {
console.log("こんにちは、" + this.name);
}
};
person.greet(); // "こんにちは、Alice"
オブジェクトの操作
プロパティの存在確認
オブジェクトに特定のプロパティが存在するかどうかを確認する方法を以下に示す。
in演算子- プロトタイプチェーンを含めてプロパティの存在を確認する。
- オブジェクト自身のプロパティだけでなく、継承したプロパティも
trueになる。
hasOwnPropertyメソッド- オブジェクト自身が持つプロパティのみを確認する。
- 継承したプロパティは
falseになる。
const person = { name: "Alice", age: 30 };
// in演算子: プロトタイプチェーンも含めて確認する
console.log("name" in person); // true
console.log("email" in person); // false
console.log("toString" in person); // true (Objectのプロトタイプから継承)
// hasOwnProperty: オブジェクト自身のプロパティのみ確認する
console.log(person.hasOwnProperty("name")); // true
console.log(person.hasOwnProperty("email")); // false
console.log(person.hasOwnProperty("toString")); // false (継承プロパティは含まない)
オブジェクト自身のプロパティのみを確認したい場合は hasOwnProperty を使用することを推奨する。
プロパティの列挙
オブジェクトのプロパティを列挙するための主要な手段を以下に示す。
Object.keys(obj)- オブジェクト自身の列挙可能なプロパティ名の配列を返す。
Object.values(obj)- オブジェクト自身の列挙可能なプロパティ値の配列を返す。
Object.entries(obj)- オブジェクト自身の列挙可能なプロパティの [キー, 値] ペアの配列を返す。
for...inループ- プロトタイプチェーンのプロパティも列挙するため、
hasOwnPropertyでフィルタリングすることを推奨する。
- プロトタイプチェーンのプロパティも列挙するため、
const person = { name: "Alice", age: 30, city: "東京" };
// Object.keys: キーの配列
console.log(Object.keys(person)); // ["name", "age", "city"]
// Object.values: 値の配列
console.log(Object.values(person)); // ["Alice", 30, "東京"]
// Object.entries: [キー, 値]ペアの配列
console.log(Object.entries(person));
// [["name", "Alice"], ["age", 30], ["city", "東京"]]
// Object.entriesとfor...ofの組み合わせ
for (const [key, value] of Object.entries(person)) {
console.log(key + ": " + value);
}
// "name: Alice"
// "age: 30"
// "city: 東京"
// for...inループ (hasOwnPropertyでフィルタリング推奨)
for (const key in person) {
if (person.hasOwnProperty(key)) {
console.log(key + ": " + person[key]);
}
}
下表に、プロパティ列挙の各手段の特性を示す。
| 手段 | 返す型 | プロトタイプチェーン | 用途 |
|---|---|---|---|
Object.keys |
キーの配列 | 含まない | キーのみ必要な場合 |
Object.values |
値の配列 | 含まない | 値のみ必要な場合 |
Object.entries |
[キー, 値]ペアの配列 | 含まない | キーと値の両方が必要な場合 |
for...in |
なし (ループ) | 含む | 特殊な場合 (hasOwnPropertyとの併用を推奨) |
関連情報
- JavaScriptの基礎 - 変数宣言
- let / const / varの宣言方法、スコープ、ホイスティング
- JavaScriptの基礎 - 分割代入
- オブジェクト/配列の分割代入、デフォルト値、残余パターン
- JavaScriptの基礎 - スプレッド構文
- オブジェクトの展開・コピー・マージ、イミュータブル更新パターン