JavaScript アドバンス

JS オブジェクト管理

1. プロパティ管理メソッド

JavaScriptでは、オブジェクトのプロパティを細かく制御するためのメソッドが用意されています。

// オブジェクトプロパティの追加または変更
Object.defineProperty(object, property, descriptor)

// 複数のオブジェクトプロパティの追加または変更
Object.defineProperties(object, descriptors)

// 特定のプロパティへのアクセス(プロパティ記述子の取得)
Object.getOwnPropertyDescriptor(object, property)

// すべてのプロパティ記述子へのアクセス
Object.getOwnPropertyDescriptors(object)

// すべてのプロパティを配列として返す
Object.getOwnPropertyNames(object)

// プロトタイプ(Prototype)へのアクセス
Object.getPrototypeOf(object)

2. JavaScript Object.defineProperty()

Object.defineProperty() メソッドは、以下の用途で使用されます。

  • オブジェクトへの新しいプロパティの追加
  • プロパティ値の変更
  • プロパティのメタデータ(Meta Data)の変更
  • オブジェクトの Getter と Setter の変更

構文:

Object.defineProperty(object, property, descriptor)

2.1 新しいプロパティの追加

この例では、オブジェクトに新しいプロパティを追加します。

// オブジェクトの作成:
const person = {
  firstName: "John",
  lastName : "Doe",
  language : "EN"
};

// プロパティの追加
Object.defineProperty(person, "year", {value:"2008"});

2.2 プロパティ値の変更

この例では、既存のプロパティ値を変更します。

// オブジェクトの作成:
const person = {
  firstName: "John",
  lastName : "Doe",
  language : "EN"
};

// プロパティの変更
Object.defineProperty(person, "language", {value : "NO"});

3. プロパティ属性 (Property Attributes)

すべてのプロパティには名前(Name)と値(Value)があります。値は、そのプロパティが持つ属性(Attribute)の一つです。

その他の属性には、enumerable(列挙可能性)、configurable(設定可能性)、writable(上書き可能性)があります。

これらの属性は、プロパティにどのようにアクセスできるか(読み取り専用か、書き込み可能かなど)を定義します。JavaScriptではすべての属性を読み取ることができますが、変更できるのは value 属性のみです(プロパティが writable である場合に限ります)。
※ECMAScript 5以降、すべてのプロパティ属性を取得および設定するためのメソッドが提供されています。

3.1 メタデータの変更

以下のプロパティメタデータを変更できます。

  • writable : true // プロパティ値を変更可能
  • enumerable : true // プロパティを列挙(列挙可能)
  • configurable : true // プロパティを再設定可能
  • writable : false // プロパティ値を変更不可
  • enumerable : false // プロパティを列挙不可
  • configurable : false // プロパティを再設定不可

また、GetterやSetterも変更可能です。

// Getterの定義
get: function() { return language }
// Setterの定義
set: function(value) { language = value }

以下の例では、language を読み取り専用に設定します。
Object.defineProperty(person, "language", {writable:false});

以下の例では、language を列挙対象から外します。
Object.defineProperty(person, "language", {enumerable:false});

4. JavaScript getOwnPropertyNames()

Object.getOwnPropertyNames() メソッドの用途:

  • オブジェクトのプロパティをリストアップする

構文Object.getOwnPropertyNames(object)

4.1 すべてのオブジェクトプロパティをリストアップする

この例では、オブジェクトのすべてのプロパティを取得します。

// オブジェクトの作成
const person = {
  firstName: "John",
  lastName : "Doe",
  language : "EN"
};

// すべてのプロパティを取得
Object.getOwnPropertyNames(person);

Object.getOwnPropertyNames() は、列挙不可(non-enumerable)なプロパティもリストアップします。

// オブジェクトの作成
const person = {
  firstName: "John",
  lastName : "Doe",
  language : "EN"
};

// languageプロパティを列挙不可に設定
Object.defineProperty(person, "language", {enumerable:false});

// すべてのプロパティを取得
Object.getOwnPropertyNames(person);

5. JavaScript Object.keys()

Object.keys() メソッドの用途:

  • 列挙可能なオブジェクトプロパティのみをリストアップする

構文Object.keys(object)

5.1 列挙可能なプロパティをリストアップする

Object.getOwnPropertyNames() の代わりに Object.keys() を使用する例です。

// オブジェクトの作成
const person = {
  firstName: "John",
  lastName : "Doe",
  language : "EN"
};

// languageプロパティを変更
Object.defineProperty(person, "language", {enumerable:false});

// すべての列挙可能なプロパティを取得
Object.keys(person);
  • getOwnPropertyNames() メソッドはすべてのプロパティを返します。
  • Object.keys() メソッドは列挙可能なプロパティのみを返します。

もし、オブジェクトのプロパティを enumerable:false を指定せずに定義した場合、これら2つのメソッドの結果は同じになります。

6. GetterとSetterの追加

Object.defineProperty() メソッドを使用して、GetterやSetterを追加することも可能です。

// オブジェクトの作成
const person = {firstName:"John", lastName:"Doe"};

// Getterを定義
Object.defineProperty(person, "fullName", {
  get: function () {return this.firstName + " " + this.lastName;}
});

6.1 カウンターの例

// オブジェクトの定義
const obj = {counter:0};

// SetterとGetterを定義
Object.defineProperty(obj, "reset", {
  get : function () {this.counter = 0;}
});
Object.defineProperty(obj, "increment", {
  get : function () {this.counter++;}
});
Object.defineProperty(obj, "decrement", {
  get : function () {this.counter--;}
});
Object.defineProperty(obj, "add", {
  set : function (value) {this.counter += value;}
});
Object.defineProperty(obj, "subtract", {
  set : function (i) {this.counter -= i;}
});

// カウンターを操作する:
obj.reset;
obj.add = 5;
obj.subtract = 1;
obj.increment;
obj.decrement;