Web制作・開発会社 プレスマンのスタッフブログ

PRESSMAN*Tech

prototypeのはなし(その1)

javaやPHPなどで慣れていると、どうしても理解しにくいのがjavascriptのprototypeとcall,applyだと思います。
別に理解できなくてもプログラム書けるんですけどね。とくにjQueryとか使っちゃうと。しかし、理解できてくるとjavascirpt超おもしろいです。
さて、prototypeがなんぞやっていうのは例によっていくらでも解説されているのでググってみて下さい。
ここではprototypeを使った例を挙げておきます。これだけでprototypeを理解する意図ではなく、理解の助けになれば程度です。


正直、prototypeについて読むだけで理解できるひとは天才じゃないかなと。普通わかんないッス。
解説を読んで、色々なソースを見たり書いたりして何となく理解した上で、もう一度しっかりと解説を読んで「おー、そういうことだったのか」となるのがいいやり方だと思います。
まあ、こんな記事を見てるよりサイ本しっかり読めばいいような気も。

とりあえず

  • functionでつくられた関数オブジェクトは全てprototypeプロパティを持っている。
  • あらゆるオブジェクトは__proto__プロパティを持っている。
  • この二つは当たり前だが別のプロパティである。
  • そして、プロトタイプチェーンって言われているのはprototypeプロパティじゃなくて__proto__プロパティのチェーン

って考えておくと理解しやすいです。
proto自体はECMAScriptで定義されている訳でなく一部の実装でのプロパティみたいだけどこれがあると考えると分かり易い)

例1

var Car = function(){};
Car.prototype.color = "black";
var car1 = new Car();
var car2 = new Car();
alert(car1.color); //black
alert(car2.color); //black

上記の例はprototypeが何かを多少でも理解していれば当たり前じゃん!といったところですね。
Carは関数オブジェクトなのでprototypeプロパティを持っています。その中身はconstructorプロパティだけを持つオブジェクトです。
つまり

Car.prototype = {constructor:Car}

みたいな感じかな?
ちなみに

Car.prototype.constructor === Car // => true

となりますが、訳わからなくなるのでconstructorはここでは無視。
car1が作成された時点でcar1にはprotoプロパティが自動で作成されてこれはCar.prototypeへ参照されます。つまり

car1.__proto__ === Car.prototype // => true

となるわけです。で、プロトタイプチェーンはそのオブジェクトが持っていないプロパティはprotoオブジェクトから探すので
car1.colorはcar1.proto.colorとなりCar.prototype.colorとなるわけでつまりblackなわけです。
car2も一緒。

つづく