この章では、#Script におけるオブジェクトについて定義する。
スクリプトによる処理の対象となる数や関数をオブジェクトと総称する。 オブジェクトは、それに付属するデータとしてメンバおよび内部メンバを 持つことができる。(厳密には、オブジェクトとはメンバと内部メンバの集合である)
メンバは名前と値の組み合わせから成る。名前は一つの Unicode 文字列であり、 値は一つのオブジェクトである。一つのオブジェクトは複数のメンバを持ち得るが、 それらはすべて異なる名前でなければならない。
またオブジェクトはメンバとは独立して内部メンバも持ち得る。 内部メンバは言語仕様の記述の簡便のために定義される形式的な存在であり、 スクリプトプログラムによって直接扱うことはできない。 内部メンバはメンバと同じく名前と値から成るが、 内部メンバの値はオブジェクトに限らない。
一つのオブジェクトには同じ名前のメンバと内部メンバが存在しても良い。 メンバと内部メンバは独立しているので、同名のメンバと内部メンバは 一般に異なる値を持つ。
名前にドル記号 $
を含むメンバの一部は、#Script
言語において特殊な意味を持つ。プログラマは、この言語仕様で定めた所定の効用
(メンバのゲッターや演算子の定義)
を得る以外の目的で名前にドル記号を含むメンバを使用すべきでない。
オブジェクトが持つメンバ・内部メンバは、 それらに対して明示的に変更が行われない限り、変化しない。
二つのオブジェクトが同じであるとは、そのオブジェクトが存在している 任意の時刻において、常に次の同値関係が成り立つことをいう: 一方のオブジェクトの任意のメンバ・内部メンバについて、 もう一方のオブジェクトも同じ名前と値のメンバ・内部メンバを持つ。
二つのオブジェクトが同じでない (異なる) ならば、 それらのオブジェクトのメンバ・内部メンバは独立している。すなわち、異なる二つの オブジェクトについて、一方のオブジェクトのメンバ・内部メンバが変化しても、 もう一方のオブジェクトのメンバ・内部メンバは直接その変化の影響を受けない。
新しくオブジェクトが作られるとき、 その新しいオブジェクトは既に存在している他のいかなるオブジェクトとも異なる。
オブジェクトがそのような種類のメンバを持っているかという観点による オブジェクトの区別を型という。#Script のオブジェクトは一般にオブジェクトの生成後にもメンバの追加や削除が行えるため、 一般にオブジェクトの型は不変ではない。
オブジェクトに $prototype
という名前の内部メンバが存在する時、
その値はオブジェクトでなければならない。オブジェクトの $prototype
内部メンバの値を、そのオブジェクトのプロトタイプオブジェクトまたは単にプロトタイプという。一般には、
オブジェクトのプロトタイプは不変ではない。また、全てのオブジェクトに
$prototype
内部メンバが存在するわけではないので、
全てのオブジェクトがプロトタイプを持つわけではない。
次の条件のどちらかが満たされるとき、オブジェクト P はオブジェクト O の準プロトタイプ (オブジェクト) であるという:
すなわち、準プロトタイプとはオブジェクトの間接的なプロトタイプのことである。
任意のオブジェクトについて、そのオブジェクトの準プロトタイプの個数は 有限でなければならない。すなわち、任意のオブジェクト O について、 次のどちらかが成り立つ:
注意: この規則は、操作 search-property がアルゴリズムとして必ず終了するために重要である。 この規則は、任意のオブジェクトはそれ自身を準プロトタイプとすることはできない ということを含意する。
オブジェクト T に prototype
という名前のメンバが存在し、そのメンバの値がオブジェクト O
のプロトタイプであるとき、O は T の真のインスタンスであるという。また、
オブジェクト T に prototype
という名前のメンバが存在し、そのメンバの値がオブジェクト O
の準プロトタイプであるとき、O は T
のインスタンスであるという。
オブジェクト O を参照先オブジェクトとし Unicode 文字列 n を参照先メンバ名とするメンバ参照に対して操作 check-property
を行うと結果が [[初期の Boolean.true
]] となり、かつ get-property/set-property/delete-property を行ったときにも何らかの意味のある結果が得られるならば、
O は n という名前のプロパティを持つという。
あるプロパティに対する操作 get-property の結果が常にオブジェクトを値とする
正常終了の結果となるとき、その結果の値をそのプロパティの値という。
プロパティの値が関数オブジェクトであるとき、
それを特にメソッドという。また、プロパティの値が常に同じ
オブジェクトであるとき、そのプロパティは不変であるという。
あるプロパティに対して操作 get-property を行うことを、そのプロパティの値の取得という。また、 プロパティに対して操作 set-property を行うことをそのプロパティに対する代入といい、操作 delete-property を行うことをそのプロパティの削除という。
あるプロパティに対する代入および削除の結果が常に
ReadOnlyError
のインスタンスを値とする
エラー終了となるとき、そのプロパティは読み取り専用であるという。
スクリプトプログラムからオブジェクトのプロパティを利用することを プロパティへのアクセスという。言語仕様の記述の簡略のため、 プロパティへのアクセスに関するいくつかの操作を以下に定める。
オブジェクトのプロパティを特定するための操作 search-property は、一つのオブジェクト o と Unicode 文字列 n に対して以下の処理を行い、一つのオブジェクトかまたは void という特殊な値を結果として返す:
スクリプトプログラムによるプロパティの取得に使われる操作 check-property はメンバ参照 r に対して次のことを行う:
$get$
を付加してできる新しい Unicode
文字列を n′ とする。操作 search-property を o と n′
に対して行い、その結果を v′ とする。Boolean.true
]] を返す。Boolean.true
]]
を返す。Boolean.false
]]
を返す。操作 check-property では、オブジェクトにプロパティが存在するかどうかを調べることが出来る。 詳細は以下の get-property の説明を参照の事。
スクリプトプログラムによるプロパティの取得に使われる操作 get-property はメンバ参照 r に対して次のことを行う:
$get$
を付加してできる新しい Unicode
文字列を n′ とする。操作 search-property を o と n′
に対して行い、その結果を v′ とする。UnsupportedOperationError
のインスタンスを投げる。操作 get-property では、オブジェクトが持つプロパティ取得のための メソッドを呼出すことによって、実際に取得される値をオブジェクトが 制御できるようにする。
例えば参照先メンバ名 abc
について操作 get-property を行うとき、
オブジェクトが $get$abc
という名前のメソッドを持っていれば、
そのメソッドを呼出してその結果を操作 get-property の結果とする。
これにより、$get$abc
というメソッドは abc
というプロパティに対するゲッターとなる。
ゲッターとして実行される関数は、get-property が取得しようとしている プロパティの値を左辺式で取得しようとしてはならない。 例えば以下のようなコードでは、操作 get-property とゲッターの呼出しが再帰的に際限なく繰り返されてしまう:
obj.$get$prop = @{ @return @this.prop; };
@printline obj.prop;
ゲッターは、代わりに #
で始まる名前のメンバを使用できる:
obj.$get$prop = @{ @return #prop; };
ゲッター関数が存在しなければ、オブジェクトが持つそのプロパティの値が そのまま返される。プロパティが存在しなければ、get-property の結果は void となる。
スクリプトプログラムによるプロパティへの代入に使われる操作 set-property はメンバ参照 r とオブジェクト p に対して次のことを行う:
$isImmutable
という名前の内部メンバが
存在すれば、新しい ReadOnlyError
のインスタンスを投げる。$set$
を付加した
新しい Unicode 文字列を n′
とする。操作 search-property を o と
n′ に対して行い、その結果を v′ とする。Boolean.false
ならば、新しい ReadOnlyError
のインスタンスを投げる。操作 set-property では、オブジェクトが持つプロパティ設定のための メソッドを呼出すことによって、実際にプロパティを設定する動作をオブジェクトが 制御できるようにする。(このメソッドは操作 delete-property でも使われる)
例えば参照先メンバ名 abc
について操作 set-property を行うとき、
オブジェクトが $set$abc
という名前のメソッドを持っていれば、
set-property に渡されたオブジェクトを引数としてそれを呼出し、その結果を返す。
これにより、$set$abc
というメソッドは abc
というプロパティに対するセッターとなる。
$set$abc
が関数ではなく false
である場合は、メンバの値は変更されず、ReadOnlyError
が投げられる。
プロパティ $set$abc
を false
にしておくことで、
プロパティ abc
は事実上読み取り専用プロパティとなる。
セッターは、set-property が設定しようとしているプロパティを左辺式への代入によって設定しては ならない。例えば以下のようなコードでは、操作 set-property とセッターの呼出しが再帰的に際限なく繰り返されてしまう:
obj.$set$prop = @[x]{ @this.prop = x; @return x; };
obj.prop = 1;
セッターは、代わりに #
で始まる名前のメンバを使用できる:
obj.$set$prop = @[x]{ #prop = x; @return x; };
セッターは、代入されたオブジェクトを戻り値として返すのが望ましい。
セッター関数が存在しなければ、指定されたオブジェクトがメンバとして そのまま設定される。
$isImmutable
内部メンバは、オブジェクトの不変性を示す。
この内部メンバが存在するオブジェクトは不変であり、メンバを変更できない。
(→Object.isImmutable
、Object.makeImmutable
)
スクリプトプログラムによるプロパティの削除に使われる操作 delete-property はメンバ参照 r に対して次のことを行う:
$isImmutable
という名前の内部メンバが
存在すれば、新しい ReadOnlyError
のインスタンスを投げる。$set$
を付加した
新しい Unicode 文字列を n′
とする。操作 search-property を o と
n′ に対して行い、その結果を v′ とする。Boolean.false
ならば、新しい ReadOnlyError
のインスタンスを投げる。Void.void
]] を返す。操作 delete-property では、オブジェクトが持つプロパティ設定のための メソッドを呼出すことによって、実際にメンバを削除する動作をオブジェクトが 制御できるようにする。(このメソッドは操作 set-property でも使われる。操作 set-property で使われるときは、呼出しにおける引数の個数が異なる)
例えば参照先メンバ名 abc
について操作 delete-property
を行うとき、オブジェクトが $set$abc
という名前のメソッドを
持つならば、引数無しでそれを呼出し、その結果を返す。
$set$abc
が関数ではなく false
である場合は、メンバの値は削除されず、ReadOnlyError
が投げられる。
プロパティ $set$abc
を false
にしておくことで、
プロパティ abc
は事実上読み取り専用プロパティとなる。
セッター関数が存在しなければ、そのまま当該メンバがオブジェクトから そのまま削除される。
delete-property では、オブジェクト自身が持つメンバのみを削除する。 プロパティの値がオブジェクトのプロトタイプオブジェクトから得られる場合では、 メンバは削除されない。