最終更新:2020-09-24 (木) 11:27:20 (30d)  

JavaScript/prototype
Top / JavaScript / prototype

JavaScriptのオブジェクトを拡張するときに使うプロパティ。

概要

  • 全ての関数オブジェクトはprototypeというプロパティを保持している
  • 関数オブジェクトを定義した直後では、このprototypeには何もプロパティを持たないシンプルなオブジェクトを参照しているが、別のオブジェクトを代入したり、新たなプロパティを設定したりする事が可能

暗黙の参照

  • その関数オブジェクトをコンストラクタとして生成されたオブジェクトは、コンストラクタのprototypeプロパティに代入されているオブジェクトに対し、暗黙の参照?を持つ。
  • つまりprototypeが指すオブジェクトがプロトタイプとなる。

メモ

  • prototypeを使ったメソッドがクラス内のローカル変数を参照している場合、その変数はインスタンス間で共有されるため、想定外の値になることがある

既存のオプジェクトの拡張

Stringオブジェクトの拡張

  • String インスタンスの全ては、String.prototype を継承します。
  • String プロトタイプオブジェクトへの変更は、String インスタンスの全てに伝播します。
    //Stringオブジェクトにhelloメソッドを追加
    String.prototype.hello= function(){
    	alert("hello")
    };
    
    //メソッドの呼び出し
    var str="test";//Stringオブジェクトの生成
    str.hello();
    
    "anyString".hello();//こういうのもできる

クラスの定義

  • //コンストラクタ
    function Hoge(arg){
    	this.text=arg.text;
    	this._mode=arg.mode;
    }
    Hoge.prototype={
    	foo:function(){
    	},
    	bar:function(){
    	}
    }
  • コンストラクタでprototype()が呼び出される

代入はprototypeをたどらない

  • function Constructor() {}
    Constructor.prototype.prop1 = 30;
    
    var objA = new Constructor();
    var objB = new Constructor();
    
    alert(objA.prop1)     // 30 と表示される。
    alert(objB.prop1)     // 30 と表示される。
    
    objA.prop1 = 100;     //代入なので新たなプロパティが作られる(暗黙の参照が切れる)
    
    alert(objA.prop1)     // 100 と表示される。
    alert(objB.prop1)     // 30と表示される
    
    Constructor.prototype.prop1=200;//プロトタイプの値を変更
    
    alert(objA.prop1)     // 100 と表示される(参照が切れている)
    alert(objB.prop1)     // 200 と表示される(暗黙に参照されている)
    
     
  • 読み取り評価の時は、暗黙の参照?をたどるが、代入やdelete演算子は、たどらない。
  • 従って objA.prop1 = 100;を行った時点で、objAそのものにprop1というプロパティが新たに作られ、そこに100が代入される。
  • よってConstructor.prototype.prop1の値は変わらないままとなる。

プロトタイプチェーン

プロトタイプを使った暗黙の参照の連鎖のこと

  • コンストラクタのprototypeには、オブジェクトも代入できますので、prototypeに代入したオブジェクトが別のオブジェクトをプロトタイプにしている事もあります。
  • そもそも全てのオブジェクトはObject.prototypeを暗黙的に参照しています。
  • こうしたプロトタイプの連鎖のことをプロトタイプチェーンと呼びます

クラス

参考