仕事でJavaScriptをよく書いていますが、大きなライブラリ的なものを書くことは少ないので、なかなか深いところまで触る機会は少ないのです。となると、必然的に、あまり使わないJavaScriptの機能は忘れてしまうということに。特に、プロトタイプ的なオブジェクト指向は、よく考えないと使い方を間違えてしまいます。

そこで、再度、ここで確認。関数の中で「this.xxx」のように定義したプロパティは、インスタンスからも利用できます。

<script>
var DogClass = function () {
  this.name = "dog";
  this.age = 20;
  this.naku = function () { return "wan!"; }
};
var taro = new DogClass();
alert(taro.age);    // 20
alert(taro.naku()); // wan!
</script>

ちなみに、関数ないで定義したローカル変数をインスタンスから使うことはできません。

<script>
var DogClass = function () {
  var name = "dog";
  var age = 20;
};
var taro = new DogClass();
alert(taro.age); // undefined
</script>

そして、prototypeを使うと、各インスタンスの中で定義された定義を共通化することができます。逆に言えば、prototypeを使わないと、インスタンスを作るたびに、個々のインスタンスに新たなプロパティが作成されます。prototypeを使うと、各インスタンスのプロパティを共通化(リンクのような感じ?)することができます。

<script>
var DogClass = function () {
  this.name = "dog";
  this.age = 20;
};
DogClass.prototype.naku = function () { return "wan!"; };
var taro = new DogClass();
alert(taro.naku()); // wan!
</script>

とは言え、インスタンスのprototypeされたプロパティを書き換えると、新たな値が生成される(リンクではなくなる)ので、値を書き換えたからといって全てのインスタンスの値が書き換わる訳ではありません。

<script>
var DogClass = function () { this.age = 20; };
DogClass.prototype.name = "dog";
DogClass.prototype.naku = function () { return "wan:" + this.name; };
var taro = new DogClass(); // インスタンス taro を作成
taro.name = "taro";        // prototypeされた値を書き換え(新たな値が生成される)
var jiro = new DogClass(); // インスタンス jiro を作成
jiro.name = "jiro";        // prototypeされた値を書き換え(新たな値が生成される)
alert(taro.naku());        // wan:taro
alert(jiro.naku());        // wan:jiro
</script>

【参考】