アクセサプロパティの基本
プロパティには、データプロパティとアクセサプロパティの2種類がある。
必ずどちらかに分類でき、両方の性質を兼ね備えることは出来ない。
データプロパティには値が格納される。
アクセサプロパティは、値は持たず、getter
やsetter
と呼ばれる関数を設定する。両方の関数を設定することも出来るし、片方だけ設定するということも可能。
以下の例では、_name
をデータプロパティとして、name
をアクセサプロパティとして、それぞれ設定している。
var person = { _name:'Tom', get name(){ console.log('_nameを読み込みます'); return this._name; }, set name(value){ console.log('_nameに'+value+'を書き込みます'); this._name = value; } }; console.log(person.name); // _nameを読み込みます // Tom person.name = 'Bob'; // _nameにBobを書き込みます console.log(person.name); // _nameを読み込みます // Bob
name
の値を読もうとするとgetter
が呼ばれ、name
に値を代入しようとすると、setter
が呼ばれる。
そのため、setter
には必ず引数が必要。引数を取らない形でsetter
を定義すると、エラーになる。
一方で、getter
にreturn
を設定しなくても、エラーにはならない。その場合はundefined
が戻り値になる。
getter
のないアクセサプロパティを読み込もうとすると、undefined
が返ってくる。
setter
のないアクセサプロパティに書き込みをしようとすると、無視され、何も起こらない。strictモードでは、エラーとなる。
// getterがない var person1 = { _name:'Tom', set name(value){ console.log('_nameに'+value+'を書き込みます'); this._name = value; } }; console.log(person1.name); // undefined // setterがない var person2 = { _name:'Tom', get name(){ console.log('_nameを読み込みます'); return this._name; } }; console.log(person2.name); // _nameを読み込みます // Tom person2.name = 'Bob'; // 何も起こらない strictモードだと、ここでエラーになる console.log(person2.name); // _nameを読み込みます // Tom
プロパティの内部属性によるgetter
とsetter
の設定
データプロパティにはなく、アクセサプロパティだけが持つ内部属性に[[Get]]
と[[Set]]
がある。それぞれ、getter
関数とsetter
関数を格納する。
この属性を操作することによって、getter
とsetter
を追加したり、内容を変更したりすることが出来る。
先ほどのコードの記法では、オブジェクト生成時にしか、getter
やsetter
を定義できなかった。
プロパティの内部属性の操作を行えるdefineProperty()
については、下記を参照。
プロパティの内部属性
// 生成した時点では、personはアクセサプロパティを持たない var person = { _name:'Tom' }; Object.defineProperty(person, 'name', { get: function(){ console.log('_nameを読み込みます'); return this._name; }, configurable: true // この属性がtrueでないと、nameプロパティを後から操作することは出来ない }); console.log(person.name); // _nameを読み込みます // Tom // ここで、getterを上書きしつつ、setterを設定する Object.defineProperty(person, 'name', { get: function(){ console.log('これは、新しく設定されたgetterです'); return this._name; }, set: function(value){ console.log('_nameに'+value+'を書き込みます'); this._name = value; } }); person.name = 'Bob'; // _nameにBobを書き込みます console.log(person.name); // これは、新しく設定されたgetterです // Bob