プロパティ操作の基本
オブジェクトのプロパティは原則的に、いつでもその内容を変更できる。
後から新しいプロパティを追加したり、既存のプロパティを削除することも出来る。
var person = { name: 'Tom' }; person.age = 30; // プロパティを追加 console.log(person.age); // 30 person.name = 'Bob'; // プロパティの値を変更 console.log(person.name); // Bob delete person.name; // プロパティを削除 console.log(person.name); // undefined
なお、そのようなプロパティの操作を防止することも出来る。詳細は下記を参照。
プロパティの内部属性
オブジェクトの変更防止
プロパティの存在確認
オブジェクトが、ある名前のプロパティを持っているかを確認する方法として、in
演算子とhasOwnProperty()
がある。
in
演算子は、対象となっているプロパティを持っていればtrue
を、持っていなければfalse
を返す。
先ほどのコードでin
演算子を使ってみる。
var person = { name: 'Tom' }; person.age = 30; // プロパティを追加 console.log('age' in person); // true person.name = 'Bob'; // プロパティの値を変更 console.log('name' in person); // true delete person.name; // プロパティを削除 console.log('name' in person); // false
in
演算子では、そのオブジェクト自身が持つプロパティだけでなく、プロトタイプ継承しているプロパティも対象とする。
自身が持つプロパティだけを確認したい場合は、全てのオブジェクトで使用可能なメソッドであるhasOwnProperty()
を使う。
このメソッドの引数にプロパティの名前を与えると、オブジェクト自身がそのプロパティ持っていればtrue
を、そうでなければfalse
を返す。
下記の例では、person
自身はtoString
を持っていないが、プロトタイプ継承しているため、in
演算子はtrue
を返す。
だがhasOwnProperty()
では、false
を返す。
var person = { name: 'Tom' }; console.log('name' in person); // true console.log('age' in person); // false console.log('toString' in person); // true console.log(person.hasOwnProperty('toString')); // false
プロパティの列挙
プロパティを列挙していく方法としては、for-in
ループ、Object.keys()
メソッド、Object.getOwnPropertyNames()
メソッドがある。
for-inループ
これは、そのオブジェクトが持っているプロパティをループで走査していく。
この方法では、プロトタイプ継承かどうかは問われず、内部属性で列挙可能になっているものが対象になる。なお、ビルトインされているほとんどのプロパティは、列挙不可になっている。
内部属性については、下記を参照。
プロパティの内部属性
var person = { name: 'Tom', age: 30, mail: 'tom@example.com' }; for(var key in person){ console.log(key); console.log(person[key]); }; // name // Tom // age // 30 // mail // tom@example.com
Object.keys()メソッド
Object.keys()
は、引数に与えたオブジェクトが持っているプロパティのリストを、配列にして返す。
対象となるのは、列挙可能かつ、自身が持っているプロパティ。列挙可能であっても、プロトタイプ継承されたものは、対象とはならない。
var person = { name: 'Tom', age: 30, mail: 'tom@example.com' }; var properties = Object.keys(person); console.log(properties); // [ 'name', 'age', 'mail' ] for(var i=0; i < properties.length; i++){ console.log(properties[i]); console.log(person[properties[i]]); }; // name // Tom // age // 30 // mail // tom@example.com
Object.getOwnPropertyNames()メソッド
Object.getOwnPropertyNames()
は、Object.keys()
とほぼ同じ機能を持つ。
違いは、Object.getOwnPropertyNames()
は、列挙不可であるプロパティも対象とするということ。
つまり、列挙可能かどうかは問わず、自身のプロパティのみを全て返す。プロトタイプ継承されたものは、全て対象外となる。
var person = { name: 'Tom', age: 30, mail: 'tom@example.com' }; // ここで、ageを列挙不可にする Object.defineProperty(person, 'age', { enumerable: false }) var properties = Object.keys(person); console.log(properties); // [ 'name', 'mail' ] properties = Object.getOwnPropertyNames(person); console.log(properties); // [ 'name', 'age', 'mail' ]
プロパティの存在確認と列挙の方法一覧
自身のプロパティ 列挙可能 |
継承されたプロパティ 列挙可能 |
自身のプロパティ 列挙不可 |
継承されたプロパティ 列挙不可 |
|
---|---|---|---|---|
in | ◯ | ◯ | ◯ | ◯ |
hasOwnProperty() | ◯ | × | ◯ | × |
for-in | ◯ | ◯ | × | × |
Object.keys() | ◯ | × | × | × |
Object.getOwnPropertyNames() | ◯ | × | ◯ | × |
出典 オブジェクト指向JavaScriptの原則 p80