2012-01-19
this と prototype の違い (Javascript)
this と prototype どっちを使えばいいのか
久々にJavascriptでもやってみようと思い、もっと深くオブジェクト思考について学んでみようと思いnewやthisといったキーワードでぐぐっていると、「prototype」というキーワードが一緒にヒットしてきました。どうやら、this でも prototypeでも同じようなことができるらしくどっちを使えばいいのか混乱してしまいました。
そこで、その違いを調べてみたのでまとめてみます。
newによるオブジェクトの生成
Javascriptでオブジェクト思考なプログラミングをするには、newが必要不可欠です。中にはnewをあえて使わずにオブジェクト思考なプログラミングをする手法もありますが、newがあることでオブジェクトを生成し、クラスのように扱うことができるようになります。
function a(){ this.a = 1; } alert(new a().a);
newでオブジェクトを生成すると、this には生成されたオブジェクトが入ります。なので、this.a = 1 とすることで生成されたオブジェクトに a という名のプロパティが作られます。
また、もしnewを入れなかった場合どうなるでしょうか。
function a(){ alert(this) } alert(a());
これを実行してみると、[object DOMWindow] と表示されます。newを使ってオブジェクトを生成しない場合は、そのページのDOMとなります。といっても、これは関数のスコープ範囲外でも同じ[object DOMWindow]となります。もちろんオブジェクトを生成したわけではないのでthis.a = 1とするとエラーとなります。
この動きを見ると、newによってオブジェクトを生成した場合は、thisを使ってプロパティを自由に定義できることがわかります。
prototype
しかし、このようにプロパティを定義する方法は他にもあります。それが「prototype」を使った方法で、関数のスコープの中でthis.a = 1 のように定義するのではなく、オブジェクトを生成する前に 関数に対して下記のようにして定義します。
function a(){} a.prototype.a = 1 alert(new a().a);
prototype とは「a.prototype.a = 1」のことですが、prototypeがいったいどこから来たものなのかわかりません。実は、このprototypeは様々な関数オブジェクトに予め定義されているものです。prototype.aに代入することで、オブジェクトを生成したときに、aのプロパティが作られます。
このように、thisでプロパティを定義する方法 と prototypeを使った方法とでは共に同じことができるので、どっちを使ったらいいのかわからなくなってしまいます。
this.a と prototype.a の違い
プロパティを定義するには、果たしてどちらがいいのでしょうか。正解を先に言ってしまうと、prototypeになります。
thisを使ってプロパティを定義した場合は、そのオブジェクト内のインスタンス変数として定義されます。newを使ってオブジェクトを作るたびに、メモリにそのプロパティの値を保管する領域が作られます。
しかし、prototypeにてプロパティを作った場合だと、そのプロパティの値を保管する領域がひとつだけになります。newを使ってオブジェクトを作るたびに、メモリにそのプロパティの値を保管する領域が次々と作られるのではなく、ひとつの保管領域に対して参照されるようになります。
prototypeを使ったほうが、thisのみを使うよりも、高速なうえにメモリの節約になります。しかも、prototypeにはもうひとつ便利な機能があって、prototypeて定義されたプロパティに新たに代入しようとすると、新しくメモリ領域が作成され、そこに保管されるようになり、prototypeへは参照されなくなるうえに、prototypeの値は変更されません。
まとめ
new prototype this でググったほうがわかりやすい。
