prototypeで実験してみた

javascriptのprototypeで色々と悩んだので、その実験を纏めてみた

まずは基本的なprototypeを使ったメソッドの実装(?)

function Human(name,age){
  this.name = name;
  this.age = age;
}
 
Human.prototype.show = function(){
  alert(this.name);
} 
  
var human = new Human("ヤマダタロウ",20);
human.show(); /* ヤマダタロウ  */


まず prototype の定義を確認する

  • 全ての関数はprototypeというオブジェクトを持つ。
  • 全てのオブジェクトは、オブジェクト生成に使ったコンストラクタのprototypeへの隠しリンクを持つ。


実験として 既にあるメソッドを定義したプロパティを別のメソッドで上書きしてみる

function Human(name,age){
  this.name = name;
  this.age = age;
  this.show = function(){
    alert("オブジェクトメソッド");
  }
}
 
Human.prototype.show = function(){
  alert("継承後メソッド");
} 
 
var human = new Human("ヤマダタロウ",20);
human.show(); /* オブジェクトメソッド */

上書きできなかった。
この結果から自分自身のプロパティの優先度が高いことがわかる。

なら、インスタンス側で新規にメソッドを定義した場合は?

function Human(name,age){
  this.name = name;
  this.age = age;
  this.show = function(){
    alert("オブジェクトメソッド");
  }
}
 
Human.prototype.show = function(){
  alert("継承後メソッド");
} 
 
var human = new Human("ヤマダタロウ",20);
human.show = function(){
  alert("インスタンスメソッド");
}
 
human.show(); /* インスタンスメソッド  */

今度はインスタンス側のメソッドが実行された。
やはり、自分自身のプロパティ値の優先度が高い。
つまり、プロパティ参照の流れは

  1. 自分自身のプロパティを参照。
  2. 存在しなければプロトタイプのフィールドを参照する。


という流れになる。
ただ、ここで問題になるのが

このshowメソッドはHumanクラスに実装されたものではない

ということ。

最初のprototypeの定義を見ると こう書かれてある

全てのオブジェクトは、オブジェクト生成に使ったコンストラクタのprototypeへの隠しリンクを持つ。

隠しリンク と書かれてある。実装とか、継承とは書かれていない。
つまり、プロパティ showは

function(){
  alert("継承後メソッド");
}

を呼び出すリンクとしての役割を持っているだけということになる。
もっとわかりやすく言うと

Humanオブジェクトは

function(){
  alert("継承後メソッド");
}

メソッドにリンクしているフィールドを持つということになる。

以上、prototypeについて勘違いしていたので纏めてみた。