まるノート

備忘録も兼ねて、様々なお役立ち情報をまとめています。

JavaScript基礎知識~プロトタイプについて~

はじめに

本記事では関数のプロパティであるプロトタイプについて解説をします。

以下の記事でも解説している通り、JavaScriptにおける関数は実行可能なオブジェクトです。なのでプロパティを持てるのです。

JavaScript基礎知識~関数について~ - まるノート

個人的にはプロパティの考え方は javascript の仕組みの中で少し難しく感じていました。
よく chrome の開発者ツール等を利用していると、[[Prototype]] というのを目にする度に、なんだろうと思いつつあまり気にしていませんでしたが、改めて学んだ内容をできる限り丁寧に解説したいと思います。


prototype オブジェクト

chrome の開発者ツールなどで適当な関数を定義し、「関数名.prototype」でアクセスすると下ようにオブジェクトが表示されるはずです。

関数もオブジェクトなのでプロパティを持てるわけですが、

関数にはprototypeと呼ばれるプロパティが存在し「関数名.prototype」でアクセスできます。
この「関数名.prototype」で表示されるオブジェクトをprototype オブジェクトと呼びます。



[[Prototype]] プロパティ

すべてのオブジェクトは[[Prototype]]というプロパティを持ちます。
上のprototypeオブジェクトの所でも見えていました。

ただしこの [[Prototype]] には直接アクセスすることはできず、アクセスするには Object.getPrototypeOf メソッドを使用します。

※[[Prototype]] 内部のプロパティが色々見えていますが、これらについてはここでは割愛します。



インスタンス化による prototype の設定

今までの内容を振り返ると、

  • 関数には prototype プロパティが存在する( 関数名.prototype でアクセス可能 )
  • すべてのオブジェクトには [[Prototype]] プロパティが存在する(Object.getPrototypeOf でアクセス可能)


そして、コンストラクタ関数から new 演算子でインスタンスを生成すると、コンストラクタ関数のもつ prototype プロパティがインスタンスの [[Prototype]] プロパティに設定されます。

以下のように二つが等価であることが確認できるはずです。



さらに、インスタンス内のプロパティにアクセスした際、該当のプロパティが見つからなかった場合には、[[Prototype]] プロパティが参照されるという仕組みがあります。
つまりコンストラクタ関数の prototype オブジェクトが参照されるということです。

[[Prototype]] が 関数名.prototype のオブジェクトを共有するといってもいいでしょう。


この仕組みのメリットは「関数名.prototype」にインスタンス共通のメソッドを定義出来る、ということです。
もちろん直接コンストラクタ関数にメソッドを定義することも出来ますが、インスタンスを生成する度にメソッドをコピーするよりもメモリ消費を抑えることができます。


インスタンスに共通のメソッドは、コンストラクタ関数の prototype オブジェクトに定義をします。

function Person(name) {
  this.name = name;
}

Person.prototype.hello = function() {
  console.log('Hello ' + this.name);
}

const taro = new Person('Taro');

console.log( taro.hello() ); // Hello Taro

上の例ですと、コンストラクタ関数 Person には直接 hello メソッドを定義していませんが、
prototypeに定義することで「taro.hello()」を呼び出すことが出来ます。


以上、プロトタイプについての説明でした。最後までご覧頂きありがとうございます。