JavaScript 逆引き集 | オブジェクトのキー列挙

JavaScript JavaScript
スポンサーリンク

オブジェクトのキー列挙(Object.keys)の基本と実践

Object.keys は「オブジェクトの“自分が持つ(自前の)列挙可能なプロパティ名”」を配列で返します。設定画面の項目一覧、テーブルのヘッダ生成、動的フォームなどでよく使います。


構文と基本ポイント

const keys = Object.keys(obj);
JavaScript
  • 返すもの: 文字列キーの配列(自身の列挙可能プロパティのみ、継承は含まない)
  • 含まれないもの: Symbolキー、非列挙プロパティ(enumerable: false)、プロトタイプ由来のプロパティ
  • 順序の目安: 数字っぽいキー(配列インデックス)→ そのほかの文字列キー(作成順)という並びになることが多い

すぐ使えるテンプレート集

1) 基本:キー一覧を取得

const user = { name: "Aki", age: 22 };
console.log(Object.keys(user)); // ["name","age"]
JavaScript
  • ポイント: 値が欲しければ Object.values、キーと値のペアなら Object.entries。

2) キー一覧から値を取り出して表示

const settings = { theme: "dark", pageSize: 20, compact: true };
const lines = Object.keys(settings).map(k => `${k}: ${settings[k]}`);
console.log(lines.join("\n"));
/*
theme: dark
pageSize: 20
compact: true
*/
JavaScript
  • ポイント: keys → map → join の定番パターン。

3) entriesで安全にループ(キーと値を同時に)

const config = { host: "localhost", port: 3000 };
for (const [k, v] of Object.entries(config)) {
  console.log(`${k} = ${v}`);
}
JavaScript
  • ポイント: entriesは「キーと値」を同時に処理できて読みやすい。

4) テーブルのヘッダ生成

const row = { id: 1, name: "Mao", city: "Tokyo" };
const headers = Object.keys(row);
console.log(`<tr>${headers.map(h => `<th>${h}</th>`).join("")}</tr>`);
JavaScript
  • ポイント: データからUIを動的生成する土台に。

5) 未知のキーを検査(存在チェック)

const obj = { a: 1, b: 2 };
const hasA = Object.keys(obj).includes("a"); // true
JavaScript
  • ポイント: 速度や明確さ重視なら "a" in objObject.hasOwn(obj,"a") も選択肢。

Object.keys と周辺APIの使い分け

  • Object.keys(obj): 自身の列挙可能な「文字列キー」一覧。
  • Object.values(obj): 自身の列挙可能な「値」一覧。
  • Object.entries(obj): 自身の列挙可能な「[キー, 値]」一覧。
  • Object.getOwnPropertyNames(obj): 自身の「非列挙も含む」文字列キー一覧。
  • Object.getOwnPropertySymbols(obj): 自身の「Symbolキー」一覧。
  • for…in: 列挙可能なプロパティを「継承分も含めて」列挙(要 hasOwnProperty で絞り込み推奨)。

実務での便利パターン

列挙可能フラグに注意(定義時に非列挙)

const obj = {};
Object.defineProperty(obj, "hidden", { value: 1, enumerable: false });
obj.visible = 2;

console.log(Object.keys(obj)); // ["visible"](hiddenは出ない)
JavaScript
  • ポイント: 設計上「出したくないキー」は非列挙にする。

文字列キーだけを対象に(Symbolは別管理)

const sKey = Symbol("secret");
const obj = { a: 1, [sKey]: 999 };
console.log(Object.keys(obj)); // ["a"]
console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(secret)]
JavaScript
  • ポイント: Symbolはメタ的な用途や衝突回避。列挙対象に含めるなら専用APIで。

配列のキー列挙(インデックスが文字列化)

const arr = ["red", "blue"];
console.log(Object.keys(arr)); // ["0","1"]
JavaScript
  • ポイント: 配列のキーはインデックス。要素値が必要ならそのまま arr を走査する方が自然。

キー一覧から型チェックやバリデーション

const payload = { id: 10, name: "Aki", extra: "x" };
const allowed = ["id", "name"];
const invalid = Object.keys(payload).filter(k => !allowed.includes(k));
console.log(invalid); // ["extra"]
JavaScript
  • ポイント: 許容キーを定義して差分で検出。

よくある落とし穴と対策

  • プロトタイプ由来が欲しいのに出ない: Object.keysは「自身のみ」。
    • 対策: for…inで列挙+hasOwnPropertyで必要に応じて切り替え。プロトタイプを明示的に辿るなら別API。
  • 非列挙プロパティが見えない: definePropertyで enumerable: false なものは落ちる。
    • 対策: 必要なら Object.getOwnPropertyNames を使う。
  • 順序を過信する: 数字っぽいキーが先に並び、その後に文字列キーが作成順というルールがあるが、設計上は「順序に依存しない」方が安全。
    • 対策: 表示順を制御したいなら別途キー配列を定義して並べ替える。
  • Mapと混同: 普通のオブジェクトは「順序保証や任意キー」に向かない。
    • 対策: キー集合が動的・順序が重要・非文字列キーを使いたいなら Map を検討。

練習問題(手を動かして覚える)

  • 1. キー一覧を「key=value」形式で出力
const obj = { a: 1, b: 2, c: 3 };
console.log(Object.keys(obj).map(k => `${k}=${obj[k]}`).join(", "));
// "a=1, b=2, c=3"
JavaScript
  • 2. 許容キー以外を検出して警告
const payload = { id: 1, name: "Mao", debug: true };
const allowed = ["id", "name"];
const extra = Object.keys(payload).filter(k => !allowed.includes(k));
console.log(extra); // ["debug"]
JavaScript
  • 3. entriesでキーと値を同時にループ
const cfg = { host: "localhost", port: 3000 };
for (const [k, v] of Object.entries(cfg)) {
  console.log(`${k}: ${v}`);
}
JavaScript
  • 4. 非列挙プロパティが keys に出ないことを確認
const obj = {};
Object.defineProperty(obj, "hidden", { value: 1, enumerable: false });
obj.visible = 2;
console.log(Object.keys(obj)); // ["visible"]
JavaScript

直感的な指針

  • 自前の列挙可能プロパティ名が欲しい: Object.keys。
  • 値一覧が欲しい: Object.values。キーと値を同時に処理したいなら Object.entries。
  • 非列挙/シンボルも含めたい: getOwnPropertyNames / getOwnPropertySymbols。
  • 順序に依存しない設計に: 表示順が必要なら自分でキー順を定義して並べる。
タイトルとURLをコピーしました