GitBookjs-primerプロトタイプオブジェクト「オブジェクト」の章では、オブジェクトの処理方法について見てきました。その中で、空のオブジェクトであってもtoStringメソッドなどを呼び出せていました。Object]"オブジェクトリテラルで空のオブジェクトを定義しただけなのに、toStringメソッドを呼び出せています。このメソッドはどこに実装されているのでしょうか?また、JavaScriptにはtoString以外にも、オブジェクトに自動的に実装されるメソッドがあります。これらのオブジェクトに組み込まれたメソッドをビルトインメソッドと呼びます。この章では、これらのビルトインメソッドがどこに実装され、なぜObjectのインスタンスから呼び出せるのかを確認していきます。詳しい仕組みについては「クラス」の章で改めて解説するため、この章では大まかな動作の流れを理解することが目的です。Objectはすべての元Objectには、他のArray、String、Functionなどのオブジェクトとは異なる特徴があります。それは、他のオブジェクトはすべてObjectを継承しているという点です。正確には、ほとんどすべてのオブジェクトはObject.prototypeプロパティに定義されたprototypeオブジェクトを継承しています。prototypeオブジェクトとは、すべてのオブジェクトの作成時に自動的に追加される特殊なオブジェクトです。Objectのprototypeオブジェクトは、すべてのオブジェクトから利用できるメソッドなどを提供するベースオブジェクトとも言えます。具体的にどういうことかを見てみます。先ほども登場したtoStringメソッドは、Objectのprototypeオブジェクトに定義があります。次のように、Object.prototype.toStringメソッドの実装自体も参照できます。"function"このようなprototypeオブジェクトに組み込まれているメソッドはプロトタイプメソッドと呼ばれます。この書籍ではObject.prototype.toStringのようなプロトタイプメソッドをObject#toStringと短縮して表記します。Object#toStringObjectのインスタンスは、このObject.prototypeオブジェクトに定義されたメソッドやプロパティをインスタンス化したときに継承します。Objectでインスタンス化したオブジェクトは、Object.prototypeに定義されたものが利用できるということです。次のコードでは、オブジェクトリテラルで作成(インスタンス化)したオブジェクトから、Object#toStringメソッドを参照しています。このときに、インスタンスのtoStringメソッドとObject#toStringは同じものとなることがわかります。Object]"このようにObject.prototypeに定義されているtoStringメソッドなどは、インスタンス作成時に自動的に継承されるため、Objectのインスタンスから呼び出せます。これによりオブジェクトリテラルで作成した空のオブジェクトでも、Object#toStringメソッドなどを呼び出せるようになっています。このインスタンスからprototypeオブジェクト上に定義されたメソッドを参照できる仕組みをプロトタイプチェーンと呼びます。プロトタイプチェーンの仕組みについては「クラス」の章で扱うため、ここではインスタンスからプロトタイプメソッドを呼び出せるということがわかっていれば問題ありません。プロトタイプメソッドとインスタンスメソッドの優先順位プロトタイプメソッドと同じ名前のメソッドがインスタンスオブジェクトに定義されている場合もあります。その場合には、インスタンスに定義したメソッドが優先して呼び出されます。次のコードでは、ObjectのインスタンスであるcustomObjectにtoStringメソッドを定義しています。実行してみると、プロトタイプメソッドよりも優先してインスタンスのメソッドが呼び出されていることがわかります。value"このように、インスタンスとプロトタイプオブジェクトで同じ名前のメソッドがある場合には、インスタンスのメソッドが優先されます。in演算子とObject#hasOwnPropertyメソッドの違い「オブジェクト」の章で学んだObject#hasOwnPropertyメソッドとin演算子の挙動の違いについて見ていきます。2つの挙動の違いはこの章で紹介したプロトタイプオブジェクトに関係しています。hasOwnPropertyメソッドは、そのオブジェクト自身が指定したプロパティを持っているかを判定します。in演算子はオブジェクト自身が持っていなければ、そのオブジェクトの継承元であるprototypeオブジェクトまで探索して持っているかを判定します。in演算子はインスタンスに実装されたメソッドなのか、プロトタイプオブジェクトに実装されたメソッドなのかを区別しません。次のコードでは、空のオブジェクトがtoStringメソッドを持っているかをObject#hasOwnPropertyメソッドとin演算子でそれぞれ判定しています。hasOwnPropertyメソッドはfalseを返し、in演算子はtoStringメソッドがプロトタイプオブジェクトに存在するためtrueを返します。true次のように、インスタンスがtoStringメソッドを持っている場合は、hasOwnPropertyメソッドもtrueを返します。trueオブジェクトの継承元を明示するObject.createメソッドObject.createメソッドを使うと、第一引数に指定したprototypeオブジェクトを継承した新しいオブジェクトを作成できます。これまでの説明で、オブジェクトリテラルはObject.prototypeオブジェクトを自動的に継承したオブジェクトを作成していることがわかりました。オブジェクトリテラルで作成する新しいオブジェクトは、Object.createメソッドを使うことで次のように書けます。trueArrayもObjectを継承しているObjectとObject.prototypeの関係と同じように、ビルトインオブジェクトArrayもArray.prototypeを持っています。同じように、配列(Array)のインスタンスはArray.prototypeを継承します。Array.prototypeはObject.prototypeを継承しているため、ArrayのインスタンスはObject.prototypeも継承しています。Object.prototypeObject.createメソッドを使ってArrayとObjectの関係をコードとして表現してみます。この疑似コードは、Arrayコンストラクタの実装など、実際のものとは異なる部分があるため、あくまでイメージであることに注意してください。Object.prototypeに定義されているメソッドを利用できます。次のコードでは、ArrayのインスタンスからObject#hasOwnPropertyメソッドが参照できていることがわかります。trueこのようなhasOwnPropertyメソッドの参照が可能なのもプロトタイプチェーンという仕組みによるものです。ここでは、Object.prototypeはすべてのオブジェクトの親となるオブジェクトであることを覚えておくだけで問題ありません。これにより、ArrayやStringなどのインスタンスもObject.prototypeが持つメソッドを利用できる点を覚えておきましょう。Array.prototypeなどもそれぞれ独自のメソッドを定義しています。Array#toStringメソッドもそのひとつです。そのため、配列のインスタンスでtoStringメソッドを呼び出すとArray#toStringが優先して呼び出されます。Object.prototypeを継承しないオブジェクトObjectはすべてのオブジェクトの親になるオブジェクトであると言いましたが、例外もあります。イディオム(慣習的な書き方)ですが、Object.create(null)とすることでObject.prototypeを継承しないオブジェクトを作成できます。これにより、プロパティやメソッドをまったく持たない本当に空のオブジェクトを作れます。undefinedObject.createメソッドはES5から導入されました。Object.createメソッドはObject.create(null)というイディオムで、一部ライブラリなどでMapオブジェクトの代わりとして利用されていました。Mapとはキーと値の組み合わせを保持するためのオブジェクトです。ただのオブジェクトもMapとよく似た性質を持っていますが、最初からいくつかのプロパティが存在しアクセスできてしまいます。ObjectのインスタンスはデフォルトでObject.prototypeを継承するため、toStringなどのプロパティ名がオブジェクトを作成した時点で存在するためです。そのため、Object.create(null)でObject.prototypeを継承しないオブジェクトを作成し、そのオブジェクトがMapの代わりとして使われていました。undefinedしかし、ES2015からは、本物のMapが利用できるため、Object.create(null)をMapの代わりに利用する必要はありません。Mapについては「Map/Set」の章で詳しく紹介します。falseまとめこの章では、プロトタイプオブジェクトについて学びました。プロトタイプオブジェクトはオブジェクトの作成時に自動的に作成されるObjectのプロトタイプオブジェクトにはtoStringなどのプロトタイプメソッドが定義されているほとんどのオブジェクトはObject.prototypeを継承することでtoStringメソッドなどを呼び出せるプロトタイプメソッドとインスタンスメソッドではインスタンスメソッドが優先されるObject.createメソッドを使うことでプロトタイプオブジェクトを継承しないオブジェクトを作成できるプロトタイプオブジェクトに定義されているメソッドがどのように参照されているかを確認しました。このプロトタイプの詳しい仕組みについては「クラス」の章で改めて解説します。