JavaScriptのReflect.ownKeys():非列挙プロパティとSymbolを含むキー一覧を取得する
Reflect.ownKeys()でオブジェクト自身のキーを漏れなく取得する方法を解説。非列挙プロパティとSymbol、キーの順序、ブラウザーとNode.jsの実行手順、例外や用途の制約を学べます。
目的:普段の一覧に出てこないキーを調べる
オブジェクトの項目を調べたとき、画面上では使えるプロパティなのに、キー一覧には見つからないことがあります。原因として、非列挙プロパティやSymbolをキーに持つプロパティが考えられます。
Reflect.ownKeys()は、オブジェクト自身が持つ文字列キーとSymbolキーを、列挙可能かどうかに関係なく取得するAPIです。ライブラリーが返すオブジェクトの調査や、設定データの意図しない項目を見つける場面に向いています。
この記事では、プロパティの値や設定をまとめて取得するのではなく、「どのキーが存在するか」の確認に絞ります。目的が通常の表示用データの処理なら、対象範囲が広いことを理解してから採用しましょう。
動作環境と対応状況
2026年11月5日時点で、MDNはReflect.ownKeys()を広く利用可能な機能として扱い、2016年9月以降、主要ブラウザー間で利用できると説明しています。現在のChrome、Edge、Firefox、Safariで利用できます。詳細はMDNのReflect.ownKeys()リファレンスを参照してください。
ブラウザー専用のAPIではないため、Node.jsでも動作します。この記事の実行環境はNode.js 22以降とします。これは例を試す対象バージョンであり、このAPIの初搭載バージョンを意味しません。追加パッケージやDOM、ネットワーク接続は不要です。
ブラウザーでの実行方法
通常のWebページを開き、開発者ツールのConsoleで、後述するJavaScriptコード全体を実行します。コードは即時実行関数で囲んでいるため、繰り返し実行してもトップレベルの変数宣言が衝突しません。Consoleが貼り付けを制限する場合は、内容を確認したうえでブラウザーの案内に従ってください。
Node.jsでの実行方法
後述するコードをUTF-8のown-keys-demo.cjsとして保存します。ターミナルで保存先のフォルダーを開き、次のコマンドを実行します。
node --version
node own-keys-demo.cjs.cjsを使うため、周囲のpackage.jsonのモジュール設定に依存せず試せます。ファイルを指定して起動する方法はNode.js公式のスクリプト実行ガイドに沿っています。
引数・戻り値と対象範囲
呼び出しの形は次のとおりです。
Reflect.ownKeys(target)- 引数
targetは調べたいオブジェクトです。配列や関数も渡せます。 - 戻り値は、キーを要素に持つ新しい配列です。各要素は文字列またはSymbolです。
- オブジェクト自身のプロパティが対象です。プロトタイプから継承したプロパティは含みません。
- 非列挙プロパティも取得します。キーがなければ空配列を返します。
null、undefined、文字列や数値などのプリミティブ値を渡すとTypeErrorになります。
列挙可能とは、プロパティのenumerableという設定がtrueであることです。通常の代入で追加したプロパティは列挙可能ですが、Object.defineProperty()では明示しない限り非列挙になります。
Object.keys()が取得するのは、自身が持つ列挙可能な文字列キーです。これに対し、今回のAPIは非列挙キーとSymbolキーも取得します。この対象範囲の違いはMDNの列挙可能性と所有権の解説で確認できます。
自己完結したコードで取得範囲を確かめる
次のコードは、継承したプロパティ、数値に見えるキー、非列挙プロパティ、Symbolキーを持つオブジェクトを作ります。出力は配列の表示形式に左右されないよう、明示的に文字列へ変換しています。
(() => {
const internalKey = Symbol("internal");
const prototype = { inherited: "親の項目" };
const settings = Object.create(prototype);
settings.title = "SEの部屋";
settings[10] = "十番";
settings[2] = "二番";
Object.defineProperty(settings, "hidden", {
value: "補助情報",
enumerable: false,
});
settings[internalKey] = "内部識別子";
const keys = Reflect.ownKeys(settings);
const labels = keys.map((key) => String(key));
console.log("全キー: " + labels.join(" | "));
console.log("通常の一覧: " + Object.keys(settings).join(" | "));
console.log("継承項目を含む: " + keys.includes("inherited"));
console.log("Symbolの同一性: " + keys.includes(internalKey));
console.log("非列挙の値: " + settings.hidden);
keys.pop();
console.log(
"配列変更後もSymbolは存在: " +
Reflect.ownKeys(settings).includes(internalKey)
);
})();仕様から導ける期待出力は次のとおりです。ここではコードを実行しておらず、実機検証結果ではありません。
全キー: 2 | 10 | title | hidden | Symbol(internal)
通常の一覧: 2 | 10 | title
継承項目を含む: false
Symbolの同一性: true
非列挙の値: 補助情報
配列変更後もSymbolは存在: truehiddenは通常の一覧から除外されますが、存在しているため値を読み出せます。非列挙という設定は、アクセスを禁止するものではありません。
また、labelsへの変換は表示のためだけです。実際のkeys配列には元のSymbolが入るため、internalKeyとの同一性を確かめられます。戻り値の配列を変更しても、元のオブジェクトからプロパティが削除されることはありません。
キーの順序を読み違えない
通常のオブジェクトでは種類ごとに並ぶ
通常のオブジェクトでは、配列インデックスに当たる文字列キーが数値の昇順で先に並び、その他の文字列キー、Symbolキーがそれぞれ作成順で続きます。
例では10を先に追加しましたが、出力は2、10の順です。これらも戻り値では数値ではなく文字列です。また、"01"や"-1"のようなキーは、この例の"2"と同じインデックス扱いにはなりません。
入力した順序をそのまま記録する用途や、表示順を業務上のルールとして管理する用途では、取得結果の順序に頼らず、別途順序を定義してください。
配列には要素以外のキーもある
配列もオブジェクトなので渡せます。ただし、取得結果は要素の添字だけとは限りません。
(() => {
const items = ["A", "B"];
console.log(Reflect.ownKeys(items).join(" | "));
})();期待出力は次のとおりです。
0 | 1 | lengthlengthは配列自身の非列挙プロパティです。したがって、キー配列の長さを配列の要素数として使うと誤りになります。
失敗例と制約
プリミティブ値は例外になる
文字列を渡して文字位置の一覧を得ようとすると失敗します。外部から受け取った値を調べる場合は、例外の扱いを決めておきます。
(() => {
try {
Reflect.ownKeys("abc");
} catch (error) {
console.log(error instanceof TypeError);
}
})();期待出力はtrueです。エラーメッセージ本文は実行環境で異なるため、比較対象にしていません。APIは同期的に配列を返すので、awaitやPromiseの拒否処理は不要です。
Symbolを文字列化すると区別が失われる
Symbol("internal")を別々に作ると、説明が同じでも異なるキーになります。どちらも表示用に変換するとSymbol(internal)になるため、その表示文字列をキーの識別や照合に使わないでください。照合には元のSymbolを保持します。
Proxyでは処理の介入や例外があり得る
通常のオブジェクトではキー取得だけでプロパティのgetterを呼び出しません。ただし、対象がProxyなら、キー一覧を取得する操作に独自処理が介入できます。順序が通常と異なる場合や、独自処理から例外が投げられる場合があります。
そのため、任意のオブジェクトを受け取る調査ツールでは、取得処理そのものをtry...catchで囲む設計が有効です。Proxyの制約違反でもTypeErrorが発生し得ます。詳細はMDNのProxyのownKeysハンドラーに記載されています。
活用事例と採用の判断
ライブラリー更新後にオブジェクトの構造が変わった疑いがある場合、このAPIで自身のキーを列挙すると、通常の一覧では見えない項目の存在を調べられます。値をすべて読み出さず、まずキーだけ確認する調査にも向いています。
設定オブジェクトの検査では、文字列キーとSymbolキーの両方を許可リストと照合できます。ただし、キーの存在だけでは値の型や妥当性までは保証できません。キーの検査と値の検査を別々に設計する必要があります。
実務での改善案は、最初に「表示用の項目を取りたいのか、構造を調べたいのか」を決めることです。表示用ならObject.keys()で十分な場合があります。非列挙プロパティやSymbolも含めた調査が必要なときにReflect.ownKeys()を選ぶと、取得範囲と目的が一致します。
公式参考資料
Googleの優先するニュース提供元にSEの部屋を追加
Googleで、いつも読みたい情報源を選べます。登録可否はGoogleの画面で確認できます。
候補にSEの部屋が表示されない場合は、まだ追加できません。