Object properties configuration¶
オブジェクトの特性をさらに深く研究する。
Property flags and descriptors¶
<https://javascript.info/property-descriptors> のノート。
Property flags¶
オブジェクトプロパティーには値のほかに三つの特別な属性がある。それらは次のフラグだ:
writableこのプロパティーの値を変更できるか否か。
enumerablefor…inループでオブジェクトプロパティーを反復させると、このプロパティーが現れるか否か。configurableこのプロパティーが削除可能であり、ここに書いた特別な属性を更新できるか否か。
通常の方法でプロパティーを作成すると、これらは true だ。
Object.getOwnPropertyDescriptor(obj, propertyName) は上述のプロパティーの情報すべてを返す。
Object.defineProperty(obj, propertyName, descriptor) は上述のフラグを変更する。このメソッドで新規プロパティーを値だけを割り当てるように定義すると、特別なフラグはすべて false となる。
Non-configurable というのは
definePropertyできないということ。
Non-writable¶
次のようにすると user.name への代入が無効化される:
let user = {
name: "John"
};
Object.defineProperty(user, "name", {
writable: false
});
user.name = "John";
“use strict” モードがオフの場合にはエラーが発生せずに、代入は静かに失敗する。この振る舞いは他のフラグに対する
definePropertyでも同様だ。nameがまだプロパティーではない場合には、無効を明示的に指定する必要はない。
Non-enumerable¶
まず、オブジェクト user にメソッド toString を普通に定義する。それから
user に対して for … in ループを書くと、このメソッドがプロパティーとして拾われる。それを避けるときには、前項の要領で enumerable: false を指定する。
Object.keys(user)の出力でもtoStringを除外する。
Non-configurable¶
組み込みオブジェクトやプロパティーには、フラグ configurable: false が設定されているものもある。例えば Math.PI を上書きしようとしても失敗する。さらに
writable: true を指定しても失敗する。
いったん
configurable: falseにすると、configurable: trueに変えることはできない。configurable: falseであっても、なぜかwritable: falseへの変更は成功する。
Object.defineProperties¶
このメソッドは一度にプロパティー複数を定義する。
Object.defineProperties(user, {
name: { value: "John", writable: false },
surname: { value: "Smith", writable: false },
// ...
});
Object.getOwnPropertyDescriptors¶
このメソッドはオブジェクトのプロパティーと特別フラグをすべて返す。
これと前項のメソッドを利用して、オブジェクトを精密に複製することができる。
Sealing an object globally¶
以上の機能はオブジェクトプロパティー単位で動作する。オブジェクト全体へのアクセスを制限する次のようなメソッドもある:
Method |
Description |
|---|---|
|
新しいプロパティーを追加するのを禁じる |
|
プロパティーを追加したり削除したりするのを禁じる |
|
さらに変更も禁じる |
テストするメソッドはめったに使われないが、次のとおり:
Method |
Description |
|---|---|
|
プロパティーの追加が禁じられているか |
|
プロパティーの追加か削除が禁じられているか |
|
プロパティーの追加か削除か変更が禁じられているか |
上のメソッド群で seal と freeze 系は特別な属性 configurable: false もセットしたりチェックしたりする。
Property getters and setters¶
<https://javascript.info/property-accessors> のノート。
オブジェクトのプロパティーは二種類ある。
データプロパティー。今まで見てきたプロパティーはすべてこの分類だ。
アクセッサープロパティー。値の取得や設定を実行するメソッドだ。
Todo
これを図式化してもいいか。
Getters and setters¶
オブジェクトリテラルに対する「値の取得や設定を実行するメソッド」を定義する方法。
let obj = {
get propName() {
// getter, the code executed on getting obj.propName
},
set propName(value) {
// setter, the code executed on setting obj.propName = value
}
};
上の定義のあと、標準的な記法 obj.propName で左辺値でも右辺値でもアクセスできる。仮に set 側メソッドの定義を与えないと、右辺値としてしかアクセスできない。
Accessor descriptors¶
既存のオブジェクトに Object.defineProperty() 系メソッドで「値の取得や設定を実行するメソッド」を定義する方法。
Object.defineProperty(obj, 'propName', {
get propName() {
// getter, the code executed on getting obj.propName
},
set(value) {
// setter, the code executed on setting obj.propName = value
}
});
アクセッサープロパティーを定義するときには
get,set,enumerable,configurableの組み合わせのみが許される。データプロパティー定義の特別属性の組み合わせと、アクセッサープロパティー定義のそれとを混ぜることは許されていない。失敗する。
Smarter getters/setters¶
ひじょうに典型的な get, set メソッドの定義例。
Using for compatibility¶
こちらもひじょうに典型的な実装例。