前回までの記事はこちらから

基礎から学ぶJavaScript1 - オブジェクトについて 基礎から学ぶJavaScript2 - コンストラクタについて

前回はコンストラクタについて勉強しました。 そして今回はその時に説明できなかったプロトタイプについてまとめました。

プロトタイプとは

関数オブジェクトを定義すると、生成されたオブジェクトに対してprototypeプロパティが自動的に生成されます。 そしてこの関数オブジェクトをコンストラクタとして生成したオブジェクトは、関数オブジェクトのprototypeプロパティを継承します。これがプロトタイプです。

プロトタイプの継承

まずはコチラをご覧ください。

var Person = function(age){
  this.age = age;
};

var yusuke = new Person(27); 
var ken = new Person(27); 

console.log(yusuke === ken);
console.log(yusuke.prototype === ken.prototype);

同じコンストラクタから生成されたyusukeとkenというオブジェクトがあります。 下の2つの式はtrue、falseどちらになるでしょうか。

上の式はfalseになります。たとえ同じ値のプロパティをもっていようが別のオブジェクトとして判定されます。 ですが下の式はtrueになります。同じコンストラクタから生成されているので二つともPersonオブジェクトのprototypeを参照するようになります。

var Person = function(){};

Person.age = 27;
var yusuke = new Person(); 
var ken = new Person(); 

console.log(yusuke.age); //27
console.log(ken.age); //27

最初に空の関数オブジェクトを定義して、prototypeにageというプロパティを追加しました。 Personオブジェクトをコンストラクタとして生成した2つのオブジェクトは両方ともageというプロパティを継承します。 2つのオブジェクト自体はageプロパティを持っていません。 オブジェクトからプロパティが見つからなかった場合は、そのオブジェクトの元のprototypeを暗黙的に参照します。 そのため二つのオブジェクトはPersonオブジェクトのprototype.ageを参照します。

var Person = function(){};

Person.prototype.age = 27;
var yusuke = new Person(); 
var ken = new Person(); 

ken.age = 28;

console.log(yusuke.age); //27
console.log(ken.age); //28

上の結果、ぱっと見当たり前な感じがするんですが、継承はどうなったんでしょうか。 kenオブジェクトには途中でageプロパティが設定されました。 そのためkenオブジェクトは自身のageプロパティを持ったため、Person.prototypeを参照しなくなったのです。 yusukeオブジェクトはageプロパティを持っていないためprototypeを参照し、2つの結果が異なる形になりました。

var Person = function(){};

Person.prototype.age = 27;
var yusuke = new Person(); 
var ken = new Person(); 

ken.age = 28;
Person.prototype.age = 29;

console.log(yusuke.age); //29
console.log(ken.age); //28

上の結果も理屈は先ほどと同じです。 kenオブジェクトにageプロパティを設定した後、prototypeにageプロパティを設定しています。 ですがkenオブジェクトは既に自身のageプロパティを持っているため、後にprototypeを設定しようが関係ないのです。

まとめ

・関数オブジェクトを定義すると、生成されたオブジェクトに対してprototypeプロパティが自動的に生成される。 ・コンストラクタから生成されたオブジェクトはコンストラクタのprototypeを参照する。 ・オブジェクトからプロパティが見つからなかった場合は、そのオブジェクトの元のprototypeを暗黙的に参照する。

下記の記事がすごく参考になりました。ありがとうございました。

JavaScriptの「プロトタイプ入門」 - Qiita プロトタイプ(prototype)によるJavaScriptのオブジェクト指向