JavaScriptでオブジェクトのプロパティ名を取得する際によく使用される`Object.getOwnPropertyNames()`メソッドについて、基本的な使い方から実践的な例まで詳しく解説します。

Object.getOwnPropertyNames()とは

`Object.getOwnPropertyNames()`は、指定したオブジェクトが直接所有するプロパティ名を配列として返すメソッドです。継承されたプロパティは含まれません。

基本的な使い方

const obj = {
  name: 'John',
  age: 30,
  city: 'Tokyo'
};

const propertyNames = Object.getOwnPropertyNames(obj);
console.log(propertyNames); // ['name', 'age', 'city']

列挙不可能なプロパティも取得できる

`Object.getOwnPropertyNames()`の特徴として、列挙不可能(non-enumerable)なプロパティも取得できます。

const obj = Object.create({}, {
  visible: {
    value: 'hello',
    enumerable: true
  },
  hidden: {
    value: 'world',
    enumerable: false
  }
});

console.log(Object.getOwnPropertyNames(obj)); // ['visible', 'hidden']
console.log(Object.keys(obj)); // ['visible']

配列での使用例

配列に対しても使用可能で、インデックスとlengthプロパティを取得できます。

const arr = ['apple', 'banana', 'orange'];
console.log(Object.getOwnPropertyNames(arr)); // ['0', '1', '2', 'length']

継承されたプロパティは含まれない

プロトタイプチェーンを通じて継承されたプロパティは結果に含まれません。

function Parent() {
  this.parentProp = 'parent';
}

function Child() {
  this.childProp = 'child';
}

Child.prototype = new Parent();
const child = new Child();

console.log(Object.getOwnPropertyNames(child)); // ['childProp']

Object.keysとの違い

`Object.keys()`は列挙可能なプロパティのみを返すのに対し、`Object.getOwnPropertyNames()`は列挙可能・不可能な両方のプロパティを返します。

const obj = Object.create({}, {
  prop1: {
    value: 'value1',
    enumerable: true
  },
  prop2: {
    value: 'value2',
    enumerable: false
  }
});

console.log(Object.keys(obj)); // ['prop1']
console.log(Object.getOwnPropertyNames(obj)); // ['prop1', 'prop2']

エラー処理

引数がnullまたはundefinedの場合、TypeErrorが発生します。

try {
  Object.getOwnPropertyNames(null);
} catch (e) {
  console.log(e); // TypeError: Cannot convert undefined or null to object
}

実践的な使用例

オブジェクトの全プロパティをコピーする場合などに活用できます。

function copyAllProperties(source) {
  const target = {};
  Object.getOwnPropertyNames(source).forEach(prop => {
    Object.defineProperty(target, prop,
      Object.getOwnPropertyDescriptor(source, prop));
  });
  return target;
}

const original = {
  name: 'John',
  age: 30
};
const copy = copyAllProperties(original);

以上が`Object.getOwnPropertyNames()`の主な使い方と特徴です。オブジェクトの操作やデバッグ時に非常に便利なメソッドとして、多くの場面で活用することができます。