プロパティ追加とは何か
オブジェクトに“新しいキー(プロパティ名)と値”を後から足すことです。ここが重要です:追加の基本は「ドット記法(静的キー)」と「ブラケット記法(動的キー)」の使い分け。さらに、オブジェクトリテラルの計算式プロパティ名、スプレッド、Object.assign、Object.defineProperty など、目的に応じた追加手段を選ぶことで、安全かつ読みやすく実装できます。
もっとも基本の追加(ドット記法とブラケット記法)
ドット記法で静的キーを追加する(最短で読みやすい)
const user = { id: 1 };
user.name = "Alice"; // 追加
user.active = true; // 追加
console.log(user); // { id:1, name:"Alice", active:true }
JavaScriptここが重要です:キーがコード上で“固定の英数字名”なら、ドット記法が最短でミスも少ないです。
ブラケット記法で動的キー・特殊キーを追加する
const product = { price: 120 };
const key = "full name";
product[key] = "Pro Pen"; // 追加(スペースを含むキー)
product["名"] = "太郎"; // 追加(日本語キー)
product[1] = "first"; // 追加(数字キーは内部的には文字列 "1")
console.log(product);
JavaScriptここが重要です:キーが変数・式・日本語・記号・スペースを含む場合は必ずブラケット記法を使います。obj.keyVar と書くと文字通り "keyVar" キーになってしまいます。
定義時にまとめて追加(オブジェクトリテラルの計算式キー)
計算式プロパティ名を使う(初期化時から動的に)
const lang = "ja";
const messages = {
title_en: "Welcome",
["title_" + lang]: "ようこそ" // "title_ja" を動的追加
};
JavaScriptここが重要です:初期化の段階でキーを組み立てたいときは、{ [式]: 値 } を使います。ドットでは動的キーを定義できません。
非破壊での追加・上書き(スプレッドと Object.assign)
スプレッドで新インスタンスへ追加(安全で読みやすい)
const base = { id: 1, name: "Alice" };
const added = { ...base, role: "admin" }; // 新しいオブジェクトに role を追加
const dynamicKey = "level";
const added2 = { ...base, [dynamicKey]: 3 }; // 動的キーの追加
JavaScriptここが重要です:共有状態(UIや設定)では“元を直接書き換えず”新インスタンスを返すのが安全。差分が明確で可読性も高いです。
Object.assign でまとめて追加
const target = { id: 1 };
Object.assign(target, { name: "Alice", active: true }); // 複数追加
JavaScriptここが重要です:assign は左側オブジェクトを“直接変更”します。非破壊にしたい場合は {} を先頭にして新インスタンスを作るのが定石です。
const merged = Object.assign({}, base, { role: "admin" });
JavaScript付加情報や制約付きの追加(defineProperty/get/set)
Object.defineProperty で属性を制御して追加
const obj = {};
Object.defineProperty(obj, "id", {
value: 1,
enumerable: false, // 列挙対象から外す
writable: false, // 書き換え不可
configurable: false // 再定義・削除不可
});
JavaScriptここが重要です:隠しプロパティ、不変設定、精密な制御が必要なときに使います。通常はリテラルやドット/ブラケットで十分です。
ゲッター/セッターで振る舞いを伴って追加
const user = {
first: "Alice",
last: "A.",
get full() { return `${this.first} ${this.last}`; },
set full(v) { [this.first, this.last] = v.split(" "); }
};
// full プロパティを“計算+更新ロジック付き”で追加した例
JavaScriptここが重要です:表示用の合成値や、セット時の検証・整形を入れたい場合に有効です。
安全性と存在判定(追加前後の確認)
存在確認を正しく行う
const obj = { a: 0, b: null };
("a" in obj); // キーの有無(true)
Object.hasOwn(obj, "a"); // “自前のキー”のみ判定(true)
obj.c === undefined; // 値未定義だが、キーが無い場合と同義ではない
JavaScriptここが重要です:値が 0 や “” でも“存在する”。キーの有無は in/Object.hasOwn で判定します。
オプショナルチェーンで“無いかも”に備える
const data = {};
// data.user.name だと TypeError、?. を使って安全に
const name = data.user?.name ?? "(unknown)";
JavaScriptプロトタイプ汚染対策(外部入力をキーにする前に)
const safe = Object.create(null); // プロトタイプなしの空オブジェクト
const inputKey = "__proto__"; // 危険キーは拒否・許可リストで制御
// safe[inputKey] = ... は継承を持たないため影響を受けにくい
JavaScriptここが重要です:外部入力のキーで直接追加しない。許可リスト(ホワイトリスト)を使うか、Object.create(null) を検討します。
配列・Map と“追加”の違い(混同しない)
配列はインデックスで追加(push/スパースに注意)
const arr = [];
arr.push("A"); // 末尾追加
arr[10] = "X"; // スロットが空の疎配列になる(推奨しない)
JavaScriptMap は set(任意型キー)で追加
const m = new Map();
m.set("id", 1);
m.set(123, "num-key"); // 数値キーもそのまま(文字列化しない)
JavaScriptここが重要です:動的で増減する辞書用途は Map が便利。既知のフィールドを持つ“レコード”用途はオブジェクトが適しています。
よくある落とし穴(重要ポイントの深掘り)
動的キーをドットで書いてしまう
const key = "role";
// NG: obj.key → "key" という文字列キー
// OK:
obj[key] = "admin";
JavaScript入れ子の非破壊更新を忘れる
const state = { prefs: { theme: "light" } };
// NG(共有参照を直接更新)
state.prefs.theme = "dark";
// OK(新インスタンスで差し替え)
const updated = { ...state, prefs: { ...state.prefs, theme: "dark" } };
JavaScript列挙順に依存した設計
オブジェクトの列挙順は仕様上“整数っぽいキーが先”。厳密な表示順が必要なら配列へ変換してソートして管理します。
まとめ
プロパティ追加は「目的に合った手段を選ぶこと」が核心です。静的キーはドット、動的・特殊文字はブラケット、初期化時の動的追加は計算式プロパティ名。共有状態ではスプレッドや Object.assign(非破壊)で安全に追加し、特殊要件は defineProperty/get/set を使う。存在判定は in/Object.hasOwn、欠損は ?./??、外部入力にはプロトタイプ汚染対策。これらを徹底すれば、初心者でも短く明快で壊れにくい“プロパティ追加”を設計できます。
