概要: このチュートリアルでは、JavaScriptオブジェクトのプロパティと、configurable、enumerable、writable、get、set、valueなどの属性について学習します。
オブジェクトのプロパティ型
JavaScriptは、[[Enumerable]]
のように二重の角括弧で囲まれた内部属性を介して、オブジェクトのプロパティの特性を指定します。
オブジェクトには、データプロパティとアクセサプロパティの2種類のプロパティがあります。
1) データプロパティ
データプロパティには、データ値の単一の場所が含まれます。データプロパティには、4つの属性があります。
-
[[Configurable]]
– プロパティがdelete
演算子を介して再定義または削除できるかどうかを決定します。 -
[[Enumerable]]
– プロパティがfor...in
ループで返されるかどうかを示します。 -
[[Writable]]
– プロパティの値を変更できることを指定します。 -
[[Value]]
– プロパティの実際の値を格納します。
デフォルトでは、オブジェクトに直接定義されたすべてのプロパティに対して、[[Configurable]]
、[[Enumerable]]
、および[[Writable]]
属性はtrue
に設定されます。[[Value]]
属性のデフォルト値はundefined
です。
たとえば、次の例では、configurable
、enumerable
、およびwritable
属性がtrue
に設定され、それぞれの値が'John'
と'Doe'
に設定された、firstName
とlastName
の2つのプロパティを持つperson
オブジェクトを作成します。
let person = {
firstName: 'John',
lastName: 'Doe'
};
Code language: JavaScript (javascript)
プロパティの属性を変更するには、Object.defineProperty()
メソッドを使用します。
Object.defineProperty()
メソッドは、3つの引数を受け取ります。
- オブジェクト。
- オブジェクトのプロパティ名。
configurable
、enumerable
、writable
、およびvalue
の4つのプロパティを持つプロパティ記述子オブジェクト。
Object.defineProperty()
メソッドを使用してオブジェクトのプロパティを定義する場合、特に指定がない限り、[[Configurable]]
、[[Enumerable]]
、および[[Writable]]
のデフォルト値はfalse
に設定されます。
次の例では、age
プロパティを持つperson
オブジェクトを作成します。
let person = {};
person.age = 25;
Code language: JavaScript (javascript)
[[Configurable]]
属性のデフォルト値はtrue
に設定されているため、delete
演算子を使用して削除できます。
delete person.age;
console.log(person.age);
Code language: CSS (css)
出力
undefined
Code language: JavaScript (javascript)
次の例では、Object.defineProperty()
メソッドを使用して、ssn
プロパティをperson
オブジェクトに追加します。
'use strict';
let person = {};
Object.defineProperty(person, 'ssn', {
configurable: false,
value: '012-38-9119'
});
delete person.ssn;
Code language: JavaScript (javascript)
出力
TypeError: Cannot delete property 'ssn' of #<Object>
Code language: PHP (php)
この例では、configurable
属性がfalse
に設定されています。したがって、ssn
プロパティを削除するとエラーが発生します。
また、プロパティを非構成可能として定義すると、構成可能に変更することはできません。
Object.defineProperty()
メソッドを使用して、writable以外の属性を変更すると、エラーが発生します。例:
'use strict';
let person = {};
Object.defineProperty(person, 'ssn', {
configurable: false,
value: '012-38-9119'
});
Object.defineProperty(person, 'ssn', {
configurable: true
});
Code language: JavaScript (javascript)
出力
TypeError: Cannot redefine property: ssn
Code language: JavaScript (javascript)
デフォルトでは、オブジェクトに定義されたすべてのプロパティのenumerable
属性はtrue
です。これは、次のようにfor...in
ループを使用して、すべてのオブジェクトプロパティを反復処理できることを意味します。
let person = {};
person.age = 25;
person.ssn = '012-38-9119';
for (let property in person) {
console.log(property);
}
Code language: JavaScript (javascript)
出力
age
ssn
次の例では、enumerable
属性をfalse
に設定して、ssn
プロパティを非列挙可能にします。
let person = {};
person.age = 25;
person.ssn = '012-38-9119';
Object.defineProperty(person, 'ssn', {
enumerable: false
});
for (let prop in person) {
console.log(prop);
}
Code language: JavaScript (javascript)
出力
age
2) アクセサプロパティ
データプロパティと同様に、アクセサプロパティにも[[Configurable]]
および[[Enumerable]]
属性があります。
ただし、アクセサプロパティには、[[Value]]
および[[Writable]]
の代わりに[[Get]]
および[[Set]]
属性があります。
アクセサプロパティからデータを読み取ると、[[Get]]
関数が自動的に呼び出されて値を返します。[[Get]]
関数のデフォルトの戻り値はundefined
です。
アクセサプロパティに値を代入すると、[[Set]]
関数が自動的に呼び出されます。
アクセサプロパティを定義するには、Object.defineProperty()
メソッドを使用する必要があります。例:
let person = {
firstName: 'John',
lastName: 'Doe'
}
Object.defineProperty(person, 'fullName', {
get: function () {
return this.firstName + ' ' + this.lastName;
},
set: function (value) {
let parts = value.split(' ');
if (parts.length == 2) {
this.firstName = parts[0];
this.lastName = parts[1];
} else {
throw 'Invalid name format';
}
}
});
console.log(person.fullName);
Code language: JavaScript (javascript)
出力
'John Doe'
Code language: JavaScript (javascript)
この例では
- まず、
firstName
とlastName
の2つのプロパティを含むperson
オブジェクトを定義します。 - 次に、アクセサプロパティとして
fullName
プロパティをperson
オブジェクトに追加します。
fullname
アクセサプロパティでは
[[Get]]
は、firstName
、space
、およびlastName
の連結の結果であるフルネームを返します。[[Set]]
メソッドは、引数をスペースで分割し、名前の対応する部分のfirstName
プロパティとlastName
プロパティを代入します。- フルネームが正しい形式、つまり、ファーストネーム、スペース、ラストネームでない場合は、エラーをスローします。
複数のプロパティを定義する:Object.defineProperties()
ES5では、Object.defineProperties()
メソッドを使用して、単一のステートメントで複数のプロパティを定義できます。例:
var product = {};
Object.defineProperties(product, {
name: {
value: 'Smartphone'
},
price: {
value: 799
},
tax: {
value: 0.1
},
netPrice: {
get: function () {
return this.price * (1 + this.tax);
}
}
});
console.log('The net price of a ' + product.name + ' is ' + product.netPrice.toFixed(2) + ' USD');
Code language: JavaScript (javascript)
出力
The net price of a Smartphone is 878.90 USD
Code language: CSS (css)
この例では、product
オブジェクトに、name
、price
、およびtax
の3つのデータプロパティと、1つのアクセサプロパティnetPrice
を定義しました。
JavaScriptオブジェクトのプロパティ記述子
Object.getOwnPropertyDescriptor()
メソッドを使用すると、プロパティの記述子オブジェクトを取得できます。Object.getOwnPropertyDescriptor()
メソッドは、2つの引数を取ります。
- オブジェクト
- オブジェクトのプロパティ
プロパティを記述する記述子オブジェクトを返します。記述子オブジェクトには、configurable、enumerable、writable、およびvalueの4つのプロパティがあります。
次の例では、前の例のproduct
オブジェクトのname
プロパティの記述子オブジェクトを取得します。
let person = {
firstName: 'John',
lastName: 'Doe'
};
let descriptor = Object.getOwnPropertyDescriptor(person, 'firstName');
console.log(descriptor);
Code language: JavaScript (javascript)
出力
{ value: 'John',
writable: true,
enumerable: true,
configurable: true }
Code language: CSS (css)
まとめ
- JavaScriptオブジェクトには、データプロパティとアクセサプロパティの2種類のプロパティがあります。
- JavaScriptは、
[[Configurable]]
、[[Enumerable]]
、[[Writable]]
、および[[Value]]
、[[Get]]
、[[Set]]
などのプロパティの特性を記述するために、[[...]]
と表記される内部属性を使用します。 Object.getOwnPropertyDescriptor()
メソッドは、オブジェクト内のプロパティのプロパティ記述子を返します。- プロパティは、オブジェクトに直接定義するか、
Object.defineProperty()
またはObject.defineProperties()
メソッドを使用して間接的に定義できます。これらのメソッドは、プロパティの属性を変更するために使用できます。