このブログ記事では、ECMAScript仕様がJavaScriptオブジェクトをどのように認識するかを詳しく見ていきます。 特に、プロパティは仕様ではアトミックではなく、複数の属性(レコード内のthinkフィールド)で構成されています。 データプロパティの値でさえ、属性に格納されています!
目次:
- オブジェクトの構造#
- Internal slots#
- Property keys#
- プロパティ属性#
- プロパティ記述子#
- プロパティの記述子の取得#
- 記述子を介して新しいプロパティを作成する#
- 記述子を介して既存のプロパティを変更する#
- Pitfall:継承された読み取り専用プロパテ 理論的根拠は、独自のプロパティを作成することによって継承されたプロパティをオーバーライドすることは、継承されたプロパティを非破壊的に変 おそらく、プロパティが書き込み可能でない場合、それを行うことはできません。
- API:property descriptors#
- オブジェクトのユースケース。getOwnPropertyDescriptors()#
- オブジェクト。getOwnPropertyDescriptors():プロパティをオブジェクトにコピーする#
- pitfall: super#
- オブジェクト。getOwnPropertyDescriptors():cloning objects#
オブジェクトの構造#
ECMAScript仕様では、オブジェクトは次のもので構成されています:
- 内部スロットは、JavaScriptからアクセスできない格納場所であり、仕様内の操作にのみアクセスできます。
- プロパティのコレクション。 各プロパティは、キーを属性(レコード内のthinkフィールド)に関連付けます。
Internal slots#
これは、仕様が内部スロットを記述する方法です(強調は私のものです)。
- 内部スロットは、オブジェクトに関連付けられ、様々なECMAScript仕様アルゴ
- 内部スロットはオブジェクトプロパティではなく、継承されません。
- 特定の内部スロット仕様に応じて、そのような状態は、任意のECMAScript言語タイプの
- または特定のECMAScript仕様タイプの値の
- の値で構成されます。
- 特に明示的に指定されていない限り、内部スロットはオブジェクトの作成プロセスの一部として割り当てられ、オブジェクトに動的に追
- 特に指定のない限り、内部スロットの初期値は値
undefined
です。 - この仕様内のさまざまなアルゴリズムは、内部スロットを持つオブジェクトを作成します。 しかし、ECMAScript言語では、内部スロットをオブジェクトに関連付ける直接的な方法は提供されていません。
- 内部メソッドと内部スロットは、二重角括弧
]
で囲まれた名前を使用して、この仕様内で識別されます。
内部スロットには二つの種類があります。
- オブジェクトを操作するためのメソッドスロット(プロパティの取得、プロパティの設定など)。)
- Data slots with storage (listed in the table below)
Internal data slot | Type |
---|---|
] |
null | object |
] |
boolean |
] |
List of entries |
Descriptions for these data スロット:
Property keys#
プロパティのキーは次のいずれかです。
- 文字列
- シンボル
プロパティ属性#
プロパティには二つの種類があり、異なる属性を持っています。
- データプロパティはデータを格納します。 その属性
value
は任意のJavaScript値を保持します。 - アクセサプロパティには、getter関数および/またはsetter関数があります。 前者は属性
get
set
に格納されます。
次の表は、すべてのプロパティ属性を示しています。
Kind of property | Name and type of attribute | Default value |
---|---|---|
Data property | value: any |
undefined |
writable: boolean |
false |
|
Accessor property | get(): any |
undefined |
set(v: any): void |
undefined |
|
All properties | configurable: boolean |
false |
enumerable: boolean |
false |
We have already encountered the attributes value
get
, and set
. The other attributes work as follows:
writable
データプロパティの値を変更できるかどうかを決定します。configurable
false
の場合、次のようになります。- プロパティを削除することはできません。
- プロパティをデータプロパティからアクセサプロパティに変更したり、その逆に変更したりすることはできません。
value
以外の属性は変更できません。- ただし、もう一つの属性変更は許可されています: あなたは
writable
true
false
.length
writable
属性を変更できるようにすると、配列をフリーズすることができます。
enumerable
Object.assign()
false
の場合、これらの操作はプロパティを無視します。
プロパティ記述子#
プロパティ記述子は、プロパティの属性をJavaScriptオブジェクトとしてエンコードします。 TypeScriptのインターフェイスは次のようになります。
疑問符は、各プロパティが省略可能であることを示します。 記述子を操作に渡すときにプロパティを省略すると、そのデフォルト値が使用されます。
プロパティの記述子の取得#
次のコードは、データプロパティのオブジェクト記述子を取得しますfirst
:次の例では、getterfullName
:
のプロパティ記述子を取得します。desc()
を使用してa行目に.deepEqual()
が動作するように回避策です。
記述子を介して新しいプロパティを作成する#
プロパティ記述子を介して新しいプロパティを作成することもできます。
記述子を介して既存のプロパティを変更する#
独自のプロパティが既に存在する場合は、記述子を介して定義すると、そのプロパティが変更されます。 一方では、割り当てのようにObject.defineProperty()
を使用することができます:
一方、Object.defineProperty()
を使用してデータプロパティをゲッターに変換することもできます(逆も同様です)。
Pitfall:継承された読み取り専用プロパテ 理論的根拠は、独自のプロパティを作成することによって継承されたプロパティをオーバーライドすることは、継承されたプロパティを非破壊的に変 おそらく、プロパティが書き込み可能でない場合、それを行うことはできません。
例を見てみましょう。
例を見てみましょう:
割り当てを介してプロパティを変更することはできません。 しかし、それを定義することで、独自のプロパティを作成することができます。
Object.defineProperty(obj, 'prop', {value: 2});assert.equal(obj.prop, 2);
セッターを持たないアクセサプロパティも読み取り専用とみなされます。
API:property descriptors#
次の関数を使用すると、プロパティ記述子を操作できます。
オブジェクトのユースケース。getOwnPropertyDescriptors()#
オブジェクト。getOwnPropertyDescriptors():プロパティをオブジェクトにコピーする#
ES6以降、JavaScriptにはすでにプロパティをコピーするためのツールメソッドがあります。Object.assign()
。 ただし、このメソッドは単純なgetおよびset操作を使用して、キーがkey
:
target = source;
つまり、次の場合にのみ、プロパティの忠実なコピーを作成します。
- その属性
writable
writable
writable
writable
writable
writable
enumerable
true
です(これが代入によってプロパティが作成される方法です)。 - これはデータプロパティです。
次の例は、この制限を示しています。 オブジェクトsource
data
であるセッターがあります。
Object.assign()
data
data
はデータプロパティに変換されます。
幸いなことに、Object.getOwnPropertyDescriptors()
Object.getOwnPropertyDescriptors()
Object.getOwnPropertyDescriptors()
data
:
pitfall: super
#
を使用するメソッドのコピーsuper
を使用するメソッドは、ホームオブジェクト(格納されているオブジェクト)としっかりと接続されています。 現在、このようなメソッドを別のオブジェクトにコピーまたは移動する方法はありません。
オブジェクト。getOwnPropertyDescriptors():cloning objects#
Shallow cloningはプロパティのコピーに似ているため、Object.getOwnPropertyDescriptors()
Object.create()
:
を使用します