プロパティとオブジェクトの関係
オレのためのJavaScript入門、その1
まず以下にサンプルコードを挙げる(一部)。
ry)...
桃月学園.レベッカ宮本 = new Object();
桃月学園.レベッカ宮本.通称 = 'ベッキー';
桃月学園.レベッカ宮本.特徴 = new Array('天才', 'ハーフ');
...(ry
ここではグローバルオブジェクト桃月学園のレベッカ宮本プロパティにオブジェクトを定義している。
ここでプロパティレベッカ宮本に保存されるのはnew Object()
で生成されるオブジェクトへの参照である。より具体的に言うとレベッカ宮本プロパティの下に定義されるプロパティ群を持つもの(=オブジェクト)のJavaScript内部における保存先の名前である。この名前はJavaScript内部でこのオブジェクトが使われる際のタグとして利用される。そしてプログラマは、彼がレベッカ宮本と名付けて定義したオブジェクトがJavaScript内部で何と呼ばれているかを知ることはできない。
このようにプロパティレベッカ宮本とここで定義されたオブジェクトとの結びつきはJavaScript内部では間接的なものである。一般的にオブジェクトを扱う言語では大抵このような仕様になっている。
なぜこのような一見無駄に思える複雑な仕様になっているのかといえば、そうすることによる利点がそれなりにあるからで、また、そうした方が実装がラクだから、ということも理由の一つかもしれない。ただこのような仕様であるがために話がややこしくなってしまう場合があるのもまた事実である。
具体的な例を挙げよう。上のサンプルコードにおいて、レベッカ宮本プロパティの指すオブジェクトにJavaScriptが「オブジェクト一号」という名前をつけたとする。その後片桐姫子プロパティや橘怜プロパティにオブジェクトを定義していくと、それぞれに内部では「二号」「三号」という名前がつけられるだろう。こうなると問題が出てくる。鈴木さやかのオブジェクトを定義する番になったときそれがたまたま6番目なら良いが、そうでなかった場合にはなにがなんだかわからなくなってしまう。(意味がわからない人はこの段落は読み飛ばしてください)
で、現実的にこの仕様が原因で問題が起こるのは主に代入処理を伴うときである。
以下のサンプルコードは(大々的に端折ってあるが)上の続きである。
ry)...
桃月学園.柏木優奈 = 桃月学園.柏木優麻;
桃月学園.柏木優奈.通称 = '優奈ちゃん';
...(ry
ここでは柏木優奈プロパティにオブジェクトを定義している。その際に彼女の双子の姉である柏木優麻プロパティの値を代入演算子=で柏木優奈プロパティに代入することによって柏木優麻プロパティに柏木優奈プロパティが参照するオブジェクトをコピーして、その後二人の異なるプロパティだけを書き換えようとしている。しかしこれは意図通りの結果にはなってくれない。この処理で柏木優奈プロパティに代入されるのは柏木優麻プロパティにオブジェクトを定義したときに作られたそのオブジェクトのJavaScript内部における保存先の名前なのである。つまりJavaScriptはプロパティ柏木優奈とプロパティ柏木優麻において同じオブジェクトを参照する。そして次の行で通称プロパティが代入されるオブジェクトは柏木優麻プロパティを定義したときに作られたオブジェクトの通称プロパティになる。これでは柏木優奈のオブジェクトを定義したことにはならない。
ではどうすればよいか。柏木優麻プロパティが指すオブジェクトを柏木優奈プロパティに正しくコピーすることができればよい……、のではあるのだが、実はオブジェクトのコピーという問題はその方法云々以前に、そもそもオブジェクトというものをコピーすることが許されるのか、という倫理的な面を含めいろいろと考慮しなければならいことが多く、とにかくメンド臭い。それはそれで興味深い問題ではあるのだけれど、とりあえずここでは保留しておく。
そんなわけで柏木優奈のオブジェクトを定義するには、たとえ柏木優麻のオブジェクトと似た要素が多くてコードを書くのが面倒でも、柏木優奈のためのプロパティを彼女のためにひとつひとつ定義していくのが最善ではないかと思う。このことはひとりの人間の定義は単に似ているからといって簡単にコピーできるものではない、ということを改めて思い出させてくれる。JavaScriptにおいて新しいオブジェクトを定義するということはつまりはそういう面倒なことであり、またそうすることによって優奈ちゃんへの愛着もまた一層深まるというものである。
まとめてみる。
JavaScript言語において新しいオブジェクトを生成するためにはnew演算子をつけてオブジェクトのコンストラクタ関数を呼び出さなければならない。こうすることがJavaScript言語における正しいオブジェクトの生成方法である。(ただしこのサンプルで桃月学園.柏木優奈 = new Object(桃月学園.柏木優麻);
とやってもうまくいかない。これはオブジェクトのコンストラクタ関数Objectがそういう仕様になっているのが原因だろうと思うのだが、個人的にはちょっと納得しにくい)
そしてオブジェクトをプロパティに代入するときに代入式で扱われる値はそのオブジェクトの内容ではなく、オブジェクトが生成されたときにJavaScriptによって付けられた名前である。
このオブジェクトとプロパティとの関係は、オブジェクトをファイルみたいなものだと考えるとわかりやすいかもしれない。プロパティに保存されるのはJavaScriptによって付けられたファイル名であり、プロパティ名が直接ファイルを指すわけではない、と。
さて次回は、この問題が起こる根本的な原因を考えてみる(予定)。
関連リンク
・ぱにぽに 氷川へきる - Google 検索
PR