はじめに
JavaScriptのオブジェクトには各プロパティに属性があり、以下の関数で確認できます。
const person = { name: "太郎" };
const descriptor = Object.getOwnPropertyDescriptor(person, "name");
console.table(descriptor);
本記事では3つのプロパティ属性について、まとめたいと思います。
- writable
- enumerable
- configurable
writable(書込可能)
対象のプロパティに値の書き込みが可能であるか or 不可であるかを示しています。
trueの場合に書き込みが可能です。
プロパティ属性の値を変更するには Object.defineProperty()
を使用します。
const person = { name: "太郎" };
Object.defineProperty(person, "name", { writable: false });
const descriptor = Object.getOwnPropertyDescriptor(person, "name");
console.table(descriptor);
それでは実際に writable が false の場合に書き込みが不可であるか試してみます。
"use strict" の有無によって結果が異なるので注意
"use strict" なし
const person = { name: "太郎" };
Object.defineProperty(person, "name", { writable: false });
person.name = "花子";
console.log(person.name);
// 太郎
最後まで実行されましたが、値の代入は行われませんでした。
"use strict" あり
"use strict";
const person = { name: "太郎" };
Object.defineProperty(person, "name", { writable: false });
person.name = "花子";
console.log(person.name);
// Uncaught TypeError: Cannot assign to read only property 'name' of object '#<Object>'
最後まで実行されず、値を代入するタイミングでエラーとなりました。
enumerable(列挙可能)
for..in
や Object.keys()
のようなプロパティを列挙する関数において、対象のプロパティを列挙するか or しないかを示しています。trueの場合にプロパティが列挙されます。
今回は Object.keys()
、Object.values()
、Object.entries()
の関数で試してみます。
enumerable が true の場合
const person = { name: "太郎", sex: "男性", age: "30" };
console.log(Object.keys(person));
console.log(Object.values(person));
console.log(Object.entries(person));
正しく "name" プロパティが列挙されました。
enumerable が false の場合
const person = { name: "太郎", sex: "男性", age: "30" };
Object.defineProperty(person, "name", { enumerable: false });
console.log(Object.keys(person));
console.log(Object.values(person));
console.log(Object.entries(person));
"name" プロパティが列挙の対象外となり、配列の長さが 2 となりました。
configurable(構成可能)
このプロパティ属性がfalseとなった場合、以下の操作が不可となります。
- enumerable 属性の変更
- オブジェクトからプロパティの削除
それぞれ実際に試してみます。
enumerable 属性の変更
const person = { name: "太郎" };
Object.defineProperty(person, "name", { configurable: false });
Object.defineProperty(person, "name", { enumerable: false });
// Uncaught TypeError: Cannot redefine property: name at Function.defineProperty (<anonymous>)
再定義が不可であるとエラーが表示されました。
ちなみに writable 属性の変更は可能です。
オブジェクトからプロパティの削除
まずは configurableがtrueの場合にプロパティが削除できるか確認します。
const person = { name: "太郎", sex: "男性", age: 30 };
delete person.name;
console.log(person);
それでは次に、configurableがfalseの場合を試してみます。
"use strict" の有無によって結果が異なるので注意
"use strict" なし
const person = { name: "太郎", sex: "男性", age: 30 };
Object.defineProperty(person, "name", { configurable: false });
delete person.name;
console.log(person);
最後まで実行されましたが、"name" プロパティの削除は行われませんでした。
"use strict" あり
"use strict";
const person = { name: "太郎", sex: "男性", age: 30 };
Object.defineProperty(person, "name", { configurable: false });
delete person.name;
console.log(person);
// Uncaught TypeError: Cannot delete property 'name' of #<Object>
最後まで実行されず、削除しようとした時点でエラーとなりました。
参考サイト