prototype図示とnewの挙動
多くの方に読んでもらえたのが何より嬉しい。
ブログ、書いて良かった、純粋に。ありがとうございます。
でも、はてぶページとか社内とかで、
「でも...もう一歩しっくりこない」という声もあって。。
話をしてて、以下の2つが理解できると、
Javascriptのprototype指向がしっくりくる(かもしれない)ことがわかった。
で、僕なりにそれをまとめてみようと思った。(くどくない程度に^^;)
それは次の(1)と(2)の理解である。
(1)prototypeとオブジェクトの関連を図でイメージする。
(2)newの挙動を把握する。
この2つをきっちり理解すれば、
少なくとももう少しprototype指向がしっくりくると思う。
だから、前の記事でよく分からなかった人は、読んでいただければと思う。
題材は前回の記事と同じく、赤い箱と青い箱を取り上げる。
var Box = function(size){ this.size = size; } Box.prototype = { color: "red" }; var redBox1 = new Box(10); var redBox2 = new Box(11); Box.prototype = { color: "blue"}; var blueBox = new Box(12);
(1)prototypeとオブジェクトの関連
まずは、(1)prototypeとオブジェクト{}の関連を図でイメージする。
オブジェクトとprototypeの関係が直観的に理解できるかもしれない。
ポイントは、
redBox1, blueBoxは、BoxやBox.prototypeを見ているのではなく、 { color: ** }のオブジェクトを指している(参照をもっている)
ということだ。
クラス指向の考えを引きずると、redBox1, blueBoxは、
BoxとかBox.prototypeを指しているように誤解しやすい。
Box.prototypeは実行時に決まるオブジェクトを指している。
(ややくどいけど)だから、上のコードの後に以下のようにすると...
Box.prototype = redBox1.prototype; Box.prototype.color = "yellow"; alert(redBox1.color); //yellow alert(redBox2.color); //yellow alert(blueBox.color); //blue
(Box.prototypeが指すオブジェクトを青い箱から赤い箱に変えた。)
これらの結果が前より納得いくものとなっていたら幸いである。
(2)newの挙動
(1)のprototypeが理解できたら、あとはnewが理解できれば、
javascriptのprototypeに大してビビることはなくなると思う。
newに関しては、僕はこの記事がすごく分かり易かった
だから、nanto_viさんの文言をお借りし、書いてみる。
例えば、この新しい青い箱を作るという処理を思い浮べて、読んでもらえればとおもう。
var blueBox = new Box(12);
"new" の挙動
- 新しいオブジェクト{}を作成する
- 1で作成したオブジェクトのprototypeに、Box(関数オブジェクト)のprototypeが格納している参照を格納する。(上の例では、{color: "blue"}オブジェクトへの参照)
- 1で作成したオブジェクトへの参照を、関数Box内のthisにセットし、関数Boxを呼び出す。引数が記述されていれば(例では12), それを関数Box実行の引数とする。
- 1で作成したオブジェクトへの参照を返す。
正確な定義はひとまず置いておいて、これがnewの挙動である。
新しく作るオブジェクトの初期化を行いたい場合ば、
Boxの処理の中に this を記述すれば、初期化処理を行うことができる。
var Box = function(size) { this.size = size; };
Box.prototypeが指すオブジェクトに影響を与えず、
新たに作成したオブジェクトにだけ処理[ex.プロパティを追加]をしている。
こうした関数オブジェクトBoxはコンストラクタと呼ばれるが、
new との協業によって新たなオブジェクトを作成していることからも、まさしくコンストラクタである。
一方、クラスというものは存在しない。
実際Ecmascriptの仕様書にも、
コンストラクタは明記されているが、クラスという言葉は出てこない。
(全部隅から隅まで見たわけではありません、、、^^;)
一般に言うクラスの役割をするのは、
まさにBox.prototypeが指しているオブジェクトであり、
これがprototype指向の核なのかな、と思った。
以上、分かっている人には当たり前の、つまらない説明かもしれないが、
少しでも納得した人がいてくれたら、幸せだなぁと思います。
prototypeを把握した上で、
prototype.jsを読んでみるのも面白いと思います。(extendとか)