
JavaScriptのオブジェクト指向:プロトタイプをきちんと理解する
はじめに
JavaScriptをより深く知りたい人のための当連載、今回が10回目です。
前回から、JavaScriptでオブジェクト指向を行うために必要な知識を解説しています。今回はその続きとして、「オブジェクトのプロトタイプ」というものについてお話ししたいと思います。
前回のおさらい
前回、JavaScriptで「クラス」を作るもっとも単純な方法として、以下のような方法をお見せしました。
function Person(name) { // this演算子を用いて、メンバを追加 this.name = name; this.hello = function() { // this演算子を用いてメンバを参照 alert("こんにちは。私の名前は" + this.name + "です。"); }; }
thisキーワードを使って、オブジェクトに変数やメソッドを追加しています。前回の記事の最後では、「この方法には問題がある」と示唆しました。
その問題とは何でしょうか?
ここで、このPersonコンストラクタを何度も呼び出して、オブジェクトを複数個作るという処理を考えてみましょう。
var shiraishi = new Person("白石"); var nakajima = new Person("中島"); var okumura = new Person("奥村");
もちろん、これら全てのオブジェクトはhello()メソッドを持ち、それぞれに対して呼び出すこともできます。
shiraishi.hello(); nakajima.hello(); okumura.hello();
何の問題もないようですが、ここには一つ大きな落とし穴があります。それは、「まったく同じコードであるhello()メソッドが、オブジェクトごとに生成される」と言うことです。
図で表すと以下のようになります。

なぜこうなるのかは、コンストラクタ内の処理を見ていただければすぐにわかるでしょう。Personコンストラクタが呼び出されると、毎回関数オブジェクトを生成し、helloと言う名前でオブジェクト自身(this)に代入しているからです。
同じ処理を行う関数オブジェクトが、オブジェクトの数と同じだけ生成されることになるので、単純に言ってメモリの無駄遣いとなります。オブジェクトの数が増えるにつれて、これは到底容認できないコストとなります。
Javaを初めとしたオブジェクト指向言語では、各オブジェクトには元になる「クラス」があり、メソッドの定義はクラスに対して行われます。つまり、オブジェクトが複数あっても、メソッドの定義は一つです。そのため、ここで問題となっているようなメモリの無駄遣いが発生しません。
JavaScriptで、こうした問題を避けるためにはどうしたらよいのでしょうか?