Object.getOwnPropertyNames とは何か
Object.getOwnPropertyNames は、オブジェクトが「自分で持っている」すべてのプロパティ名を配列で返すメソッドです。
「自分で持っている」というのは、プロトタイプ(継承元)から来たものではなく、そのオブジェクト自身に定義されているプロパティのことです。
const obj = { a: 1, b: 2 };
const names = Object.getOwnPropertyNames(obj);
console.log(names); // ["a", "b"]
JavaScriptここが重要です:Object.keys と違い、Object.getOwnPropertyNames は 「列挙できないプロパティ(non-enumerable)」も含めて全部返す という特徴があります。
Object.keys との違いから理解する
Object.keys は「列挙可能なプロパティ」だけ
まずは Object.keys との違いを押さえるとイメージしやすいです。
const obj = { a: 1, b: 2 };
Object.defineProperty(obj, "hidden", {
value: 42,
enumerable: false // 列挙不可
});
console.log(Object.keys(obj)); // ["a", "b"]
console.log(Object.getOwnPropertyNames(obj)); // ["a", "b", "hidden"]
JavaScriptここが重要です:
Object.keys(obj)
→ ループで回せる「列挙可能な」プロパティだけObject.getOwnPropertyNames(obj)
→ 列挙可能かどうかに関係なく、「自分のプロパティ」を全部
言い換えると、Object.getOwnPropertyNames は 「見えるものも、裏でこっそり持っているものも含めて全部」 取り出すイメージです。
プロトタイプ由来のプロパティは含まれない
Object.getOwnPropertyNames は、「そのオブジェクト自身のプロパティ」だけを返します。
継承元(プロトタイプ)のプロパティは含みません。
const parent = { a: 1 };
const child = Object.create(parent); // parent をプロトタイプに持つオブジェクト
child.b = 2;
console.log(Object.getOwnPropertyNames(child)); // ["b"]
JavaScriptchild は a も見えますが、それは parent からの継承なので「自分のプロパティ」ではありません。
そのため Object.getOwnPropertyNames(child) には入ってきません。
基本的な形と戻り値をしっかり確認する
シンプルなオブジェクトでの動き
const user = { id: 1, name: "Alice" };
const names = Object.getOwnPropertyNames(user);
console.log(names); // ["id", "name"]
JavaScript戻り値は「文字列の配列」です。
順番はだいたい「定義した順」に近いですが、厳密な順番は仕様に少しルールがあります(初心者のうちはあまり気にしなくてOKです)。
配列に対して使うとどうなるか
配列も実は「数字のプロパティ名を持ったオブジェクト」なので、Object.getOwnPropertyNames を使えます。
const arr = ["a", "b"];
const names = Object.getOwnPropertyNames(arr);
console.log(names); // ["0", "1", "length"]
JavaScriptここが重要です:
配列に対して使うと、インデックス "0", "1" と、"length" プロパティまで見えます。
内部的なプロパティも含めて「そのオブジェクトが持っているもの全部」を見たいときに役立ちます。
どんなときに使うメソッドなのか(実務寄りのイメージ)
デバッグや調査で「隠れたプロパティ」まで全部見たいとき
ライブラリや他人のコードで作られたオブジェクトが、
「どんなプロパティを持っているのか」を調べたいときに便利です。
function debugProps(obj) {
const names = Object.getOwnPropertyNames(obj);
console.log("プロパティ一覧:", names);
}
const user = { name: "Alice" };
Object.defineProperty(user, "_id", {
value: 123,
enumerable: false
});
debugProps(user);
// プロパティ一覧: ["name", "_id"]
JavaScriptObject.keys だけでは _id のような「隠しっぽい」プロパティは見えませんが、Object.getOwnPropertyNames なら見えます。
ライブラリっぽい処理で「オブジェクトを丸ごと扱いたい」とき
例えば、「オブジェクトのすべてのプロパティに対して、ある処理を一括で行いたい」ような関数を作るとき、Object.getOwnPropertyNames を使うと、enumerable に関係なく全部触れます。
function cloneAllProps(obj) {
const clone = {};
for (const key of Object.getOwnPropertyNames(obj)) {
clone[key] = obj[key];
}
return clone;
}
JavaScriptただし、こういった「全部コピー」の処理は Object.assign も候補になるので、
「列挙不可のものも含めたいのか?」をよく考えてから選ぶことが大事です。
プロパティディスクリプタとの組み合わせ(少し踏み込んだ話)
getOwnPropertyNames → getOwnPropertyDescriptor で詳細を見る
Object.getOwnPropertyNames は「名前一覧」を返してくれます。
その名前を使って Object.getOwnPropertyDescriptor を呼ぶと、
各プロパティが「書き込み可能か」「列挙可能か」などの詳細を調べることができます。
const obj = {};
Object.defineProperty(obj, "hidden", {
value: 123,
writable: false,
enumerable: false,
configurable: false
});
for (const name of Object.getOwnPropertyNames(obj)) {
const desc = Object.getOwnPropertyDescriptor(obj, name);
console.log(name, desc);
}
JavaScript出力イメージ(概念)としては、
hidden { value: 123, writable: false, enumerable: false, configurable: false }
JavaScriptのようになります。
ここが重要です:getOwnPropertyNames は「何があるか」を知る入口、その先で必要に応じて getOwnPropertyDescriptor などと組み合わせていく、という使い方をします。
初心者のうちは、「そういう詳しい調査もできるんだな」くらいの理解で十分です。
Object.keys / Object.getOwnPropertyNames / for…in の整理
3つをざっくり使い分けるイメージ
似たことをする機能がいくつかあるので、ここで一度整理します。
Object.keys(obj)
→ 「自分の」「列挙可能な」プロパティ名だけ
Object.getOwnPropertyNames(obj)
→ 「自分の」「列挙可能・不可能に関係なくすべて」のプロパティ名
for...in
→ 「自分+プロトタイプから継承した」「列挙可能な」プロパティ名を順に取得
コードで比べてみます。
const parent = { parentProp: 1 };
const child = Object.create(parent);
Object.defineProperty(child, "hidden", {
value: 42,
enumerable: false
});
child.visible = 100;
console.log("keys:", Object.keys(child)); // ["visible"]
console.log("getOwnPropertyNames:", Object.getOwnPropertyNames(child)); // ["hidden", "visible"]
console.log("for...in:");
for (const key in child) {
console.log(key); // "visible", "parentProp"
}
JavaScriptここが重要です:
- 普通のループ・処理には
Object.keys(+実際の値はobj[key])がよく使われる - 「隠れたプロパティまで全部知りたい」ときだけ
Object.getOwnPropertyNames for...inはプロトタイプも含めてしまうので、初心者には少し扱いが難しい
Object.getOwnPropertyNames は、どちらかというと「調査・内部実装向け」のメソッド、
という位置づけで覚えておくと、使いどころを間違えにくくなります。
例題で理解を固める
// 1) 通常のオブジェクト
const user = { id: 1, name: "Alice" };
console.log(Object.getOwnPropertyNames(user)); // ["id", "name"]
// 2) 列挙不可プロパティを含めて取得
const obj = {};
Object.defineProperty(obj, "hidden", {
value: 42,
enumerable: false
});
obj.visible = 100;
console.log(Object.keys(obj)); // ["visible"]
console.log(Object.getOwnPropertyNames(obj)); // ["hidden", "visible"]
// 3) 配列に対して使う
const arr = ["a", "b"];
console.log(Object.getOwnPropertyNames(arr)); // ["0", "1", "length"]
// 4) プロトタイプを持つオブジェクト
const parent = { parentProp: 1 };
const child = Object.create(parent);
child.childProp = 2;
console.log(Object.getOwnPropertyNames(child)); // ["childProp"]
// 5) 全プロパティの名前と値をログ出力するユーティリティ
function logOwnProps(obj) {
for (const name of Object.getOwnPropertyNames(obj)) {
console.log(`${name}:`, obj[name]);
}
}
logOwnProps(obj);
// hidden: 42
// visible: 100
JavaScriptまとめ
Object.getOwnPropertyNames の核心は、
「そのオブジェクトが“自分で持っている”すべてのプロパティ名(列挙不可も含む)を配列で返す」 ことです。
ポイントを整理すると、
Object.keysより“強い”版で、hidden なプロパティも見える- プロトタイプ由来のプロパティは含まれない(あくまで「自分のもの」だけ)
- デバッグやライブラリ実装などで、「オブジェクトの正体を調べたい」ときに特に役立つ
getOwnPropertyDescriptorなどと組み合わせると、プロパティの詳細情報まで追える
という位置づけになります。
日常のアプリコードでは Object.keys や Object.entries が主役になることが多いですが、Object.getOwnPropertyNames を理解しておくと、「なぜここだけこれを使っているのか?」という場面で納得しやすくなり、
オブジェクトの仕組みに対する理解も一段深くなっていきます。
