忍者ブログ

非公開:代入式の中で何が起こっているか

Powered by 
NinjaBlog

[39][38][37][36][35][34][33][32][31][30][29]

[PR]

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

この記事のURL

...2024.11.22 17:55

代入式の中で何が起こっているか

オレのためのJavaScript入門、その2

 まずはサンプルコードを挙げる。
・サンプル1

片桐姫子.所属 = 'C組';
橘玲.所属 = 片桐姫子.所属;

・サンプル2

片桐姫子.所属 = new Array('C組');
橘玲.所属 = 片桐姫子.所属;

 とりあえずなんとなくサンプル1のようなコードを書いてみたが、後のことを考え所属プロパティを配列にしたサンプル2に書き直した。こうすると後で片桐姫子.所属.push('漫研');みたいなことができてなかなか具合が良いではないか。
 今回はこの2つのコードの違いについて考えてみる。

 さてこの2つのコードにほとんど違いはない。2行目については全く同じである。にもかわらず内部では異なるデータ構造が出来上がる。その違いはそれぞれのコードで姫子をD組にトレードしてみるとわかる。
 ・サンプル1の場合

片桐姫子.所属 = 'D組';

 ・サンプル2の場合

片桐姫子.所属[0] = 'D組';

 サンプル1では姫子だけがD組に放出されるのに対し、サンプル2では玲までがその巻き添えをくらっている。
 これはこのコードに問題があるからであって、ではどこにその問題があるかというと、玲の所属プロパティに姫子の所属プロパティを代入している部分である。これは前回に説明した通り。そうなると次に問題になるのはサンプル2ではなく、サンプル1がプログラマの意図通りに動いてしまうことになる。これはいったいどうしてだろう。
 この原因は代入式の扱う値が文字列ときと配列のときの処理に違いにある。
 代入式の右辺値の値が文字列のとき左辺値のプロパティが受け取る値は、演算子=によって書き写された右辺値の文字列そのものである。つまり文字列はオブジェクトではなく値として扱われる。左辺値のプロパティには右辺値の文字列が文字通り代入される。文字列をオブジェクト風に考えると、このとき左辺値の指すオブジェクトは右辺値の指すオブジェクトと同じ内容で参照先の異なるオブジェクトということになるが、先に書いたように文字列はオブジェクトではないのでこの考え方はやはり正確とはいえない。
 では代入式の右辺値が配列のときはどうだろう。配列はオブジェクトである。つまり橘玲.所属 = 片桐姫子.所属;で扱われる値は配列への参照ということになり、玲は姫子と運命を共にしなければならなくなる。

 原因はわかった。要はプログラマが扱う値の種類を正しく把握し、管理すれば問題は起こらないということだ。これで問題は解決、メデタシメデタシ。
 と言いたいところだが、この問題の本質は内部で何が起こっているかではなく、見た目上ほぼ同一のコードから異なる結果が導き出されることにある。本題(JavaScript)から少し離れるが、このことを少し突っ込んで考えてみる。

 プログラマが出す同じ指示に対してコンピュータが勝手に違う処理をされてはかなわない。これは「仕事をしなさい」という指示を受けた部下が急に飯を食いだしたり居眠りを始めたりするようなものだ。後で「寝るのも仕事のうちです」とか開き直られても、困る。
 細かく見ていけばサンプル2の1行目にはnew演算子があるので、この時点で代入式の扱う値はオブジェクトへの参照であることはわかる。だがこれだけでは決してわかりやすいとはいえないだろうし、実際にはnew演算子による代入式が近くにあるとは限らない。
 あるいは見た目上全く同じであるプロパティという器に対して「値」と「オブジェクトへの参照」という全く異質なものを乗せることができてしまうことの方が問題なのかもしれない。レストランのテーブルでお皿に乗ったメニューが出てきたらそれは混乱するだろう。事実、参照値を扱う際の入れ物に対して通常の変数とは異なる記法をとる言語だってあるし、それは特に珍しいことでもない。

 そもそもどうしてオブジェクトを値として直接扱わず、参照されるものとして間接的に扱うのだろう。
 これはオブジェクトが構造を伴った情報であること、そして場合によっては情報量がとてつもなく大きくなる可能性があることが原因ではないかと思う。複雑で巨大なものを直接扱うのは効率が悪い、という現実世界の常識をコンピュータ言語の世界に取り入れたものといえるかもしれない。
 落語に「風呂屋と豆腐屋」という噺がある。毎日豆腐を売り歩かなければならない豆腐屋が番台に座っているだけの風呂屋に延々と愚痴を言う、という他愛もない噺なのだが、これなどは値的な扱い(=豆腐屋)とオブジェクト的な扱い(=風呂屋)のたとえ話として聞くとなかなかおもしろい。あるいは夫婦という関係はお互いを値的に扱った関係で、キャバクラやホストクラブに行くのはオブジェクト的に……。いやいや、要するにどちらの扱いにも欠点はあるがそれを補って余りある利点がある、ということを言いたいワケだ。
 となると今度は参照と値とに同じ表現を用いることに対する問題が残る。同じものの複製を作ることと、ひとつのものに複数の関連付けを行うこととは本質的にまったく異なる。しかし振る舞いにおいては変わりがないことも多い。実際、内容に変化を加えない限りにおいてその振る舞いは完全に同じである。映画館まで出かけようが(=オブジェクト的扱い)DVDを買ってきて家で見ようが(=値的扱い)映画の内容に変わりはない。
 それならいっそ同じ表記にした方がわかりやすいのではないか、ということかもしれない。あるいは単に新しい表記を考えるのがメンド臭かっただけかもしれない。

 このことは肯定的な言葉で「臨機応変」と言われる。つまり一概に「悪い」とは決め付けられない。ではあるが、このいわば重複した仕様のせいでJavaScriptを学ぶ人がほぼ必ず一度はつまずかざるを得ないのもまた事実である。
 ちなみに「風呂屋と豆腐屋」では風呂屋と豆腐屋は幼馴染で二人とも新婚という設定になっていて、豆腐屋の愚痴が実は単なるノロケ話だったことに対して最後に風呂屋が「残り湯は、犬も食わねえ」とオチるのだが、実はこの豆腐の「食える」と残り湯の「食えない」という特徴は値とオブジェクトの特徴と似ている、という話はまた次回に。

 ついでに言っておくとこの「風呂屋と豆腐屋」という噺は完全に私のでっちあげなのでオブジェクト的には取り扱わないように。あくまで値的に扱ってください。
 はい、おあとがよろしいようで。(よろしくない)

PR
[39][38][37][36][35][34][33][32][31][30][29]
忍者ブログ [PR]
コンテンツ
カテゴリ別アーカイブ
月別アーカイブ
最新コメント
ブログ内検索

Since 2005 (C) hya All Rights Reserved.