JavaScriptの.__proto__とprototypeとinstance

# 初めに
inheritanceについて書くとき、自分がプロトタイプチェーンへの認識が足りないと認識したから、もう一度調べてまとめてみました。読みやすくなるため相関図も作ってみました。
主な参考資料はこちらです↓
[How does JavaScript .prototype work? - stackoverflow](https://stackoverflow.com/questions/572897/how-does-javascript-prototype-work)
[__ proto __ VS. prototype in JavaScript](https://stackoverflow.com/questions/9959727/proto-vs-prototype-in-javascript)

自分の考えと考察も入れてこの文章を書きましたので、自分勝手の解釈も含みます。

まずは名詞の解釈について：
- `.__proto__`：プロトタイプチェーンの参照（reference）、プロトタイプチェーンの本体です。（隠しプロパティ[[prototype]]を暴くアクセサープロパティ）
- `prototype`：原型であり継承（親）オブジェクトの参照（reference）でもあります。組み込みメソッド(built-in function)もコンストラクタ関数（constructor function）にも各自の参照元があります。
- `instance`：インスタンス、複製先。
- `constructor`：コンストラクタ、構築子、複製元を記録するオブジェクト。

# TL;DR
- `instance（インスタンス）`　⇒　コンストラクタ関数のなかみを完全に複製したもの。
- `.__proto__`　⇒　プロトタイプチェーンの参照先として、インスタンス自体持ってないプロパティやメソッドを、見つけるまで上へを辿っていく。（なかった場合は`undefined`）
- `prototype`　⇒　（もとからある`Function.prototype`、`Object.prototype`、`null`を除いて）コンストラクタ関数の創り出されると同時に`prototype`が形成され、インスタンスの`.__proto__`になる。


# 今回デモのコードの相関図
![relationship1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2477698/e96b8b93-88cf-38ce-46c4-ecef0da30895.png)
初めからこの図読むとこれ何なのか分からないと思います。
一番最後にまた読みましょう。

ここから、なぜ先ほど名詞の解釈がそうなったのか、図と検証で説明したいと思います。

# .__ proto __ & prototype
**`.__proto__`はプロトタイプチェーンの参照先、プロトタイプチェーンの本体です。**
`.__proto__`は定義上では`prototype`とまったく違うものです。でもよく間違われるのは、両者が判定が`true`になるためではないかと。

最初[prototypeについて](https://qiita.com/hu-yu/items/d6d9f3ca0f1dd98f2bcc)書くとき、この二つの違いが何となく分かるけど、決定的な何かが分かりません。（笑）少し検証したけれど、何かいけそうで文章を書いたが、実際この二つを混同して語ってたことが今になって気づきましたが。

なので、ここから両者の違いを検証から入りたいと思います。
```jsx
function Person() { }
const newPerson = new Person()

console.log(Person.__proto__) // {}
console.log(Person.prototype) // {}

console.log(Person.__proto__ === Person.prototype) // false
console.log(Person.__proto__ === Function.prototype) // true

console.log(Object.getPrototypeOf(Person) === Person.prototype) // false
console.log(Object.getPrototypeOf(Person) === Function.prototype) // true
```
コンストラクタ関数`Person`の`.__ proto __`と`prototype`が同じく`{}`をログしたが、見た目は同じだが、実際は別物です。（隠しプロパティ[[property]]の中身が違うから）

`.__proto__`が非推奨になったので`Object.getPrototypeOf()`を使い[[prototype]]の`.__proto__`プロパティを見つけ出します。もちろん結果は同じですが。
(正直この関数の名前からすると`prototype`を探すことだと誤解しがちですね。)

`Person`の`.__ proto __`、実は`Function.prototype`です。
ではこの`Function.prototype`一体何でしょうか？
ここは検証は長い～長い～ことになるから後に付けるから図を見てみましょう。
![relationship2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2477698/6023876f-8dbd-dbd0-1f84-16b609b7e08f.png)
`Function.prototype`は、`Function`の`prototype`です。（説明になってないじゃんー！）
ちょっとお待ちを！ここで`prototype`の解釈をもう一度見てください！
**`prototype`：原型であり継承（親）オブジェクトの参照（reference）でもあります。組み込みメソッド(built-in function)もコンストラクタ関数（constructor function）にも各自の参照元があります。**
`prototype`は参照元だから、`Function.prototype`はつまりJavaScriptで使えるすべて`Function`（built-in function）の参照元ということです。

どうしてそんなに言い切れるんでしょうか？
実際に検証してみたらその関連性を発覚しました。
```jsx
console.log(String.__proto__ === Function.prototype) // true
console.log(Number.__proto__ === Function.prototype) // true
console.log(BigInt.__proto__ === Function.prototype) // true
console.log(Boolean.__proto__ === Function.prototype) // true
// console.log(undefined.__proto__ === Function.prototype)
// TypeError: Cannot read property '__proto__' of undefined
console.log(Symbol.__proto__ === Function.prototype) // true
// console.log(null.__proto__ === Function.prototype)
// TypeError: Cannot read property '__proto__' of undefined

console.log(Object.__proto__ === Function.prototype) // true
console.log(Array.__proto__ === Function.prototype) // true
console.log(Function.__proto__ === Function.prototype) // true

console.log(Person.__proto__ === Person.prototype) // false
console.log(Person.__proto__ === Function.prototype) // true
```
```jsx
console.log(Person.prototype) // {}
console.log(Person.prototype.__proto__ === Object.prototype) // true
console.log(Function.prototype.__proto__ === Object.prototype) // true
console.log(Object.prototype.__proto__ === null) // true
```
（undefinedとnullにはそもそも`.__proto__`プロパティがないため利用できるメソッドはないということも分かりました。）

`console.log(Person.__proto__ === Person.prototype) // false`以外、すべての`.__proto__`が`Function.prototype`でした。

ここで気を付けることが二つあります。
`.__proto__`は`prototype`と意味上イコールではないこと。
`.__proto__`はあくまでも参照先を示すこと。

コンストラクタ関数`Person`の原型は間違いなく`Person.prototype`ですが、この`prototype`のなかに何も入っていません。空のオブジェクト`{}`です。もし`Person.prototype`が関数`Person`のプロトタイプチェーンであれば、JavaScriptの組み込みメソッド（built-in function）が使えません。なぜなら、`Person.prototype`の上は`Object.prototype`になるから、つまりメソッドを持つ`Function.prototype`がスキップされることになります。

なので`console.log(Person.__proto__ === Function.prototype) // true`で分かったように、`.__proto__`は**チェーンの参照**として、JavaScriptの元からある組み込みメソッドを使わせるためにプロトタイプチェーンの参照元を示しました。

これで`〇〇.prototype`が`.__proto__`（参照先）になりますが、言葉の意味としてイコールではないことが分かりやすくなると思います。
![relationship3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2477698/b4bba66d-496b-22fa-0f41-647f95b33803.png)
プリミティブもオブジェクトもすべての`.__proto__`が`Function.prototype`なので組み込みメソッド(built-in function)を継承して使えるようになったのです。

では`Person`のインスタンス`newPerson`はどうなるでしょう。
図から見ると`newPerson`は`Function.prototype`をスキップしたんじゃないんですか？

いい質問ですね。これが「継承関係」一番のかなめだと思います。
次の **.__ proto __ & instanceof** で説明したいと思います。


補足：↓は`newPerson`の`.__proto__`の検証です。
```jsx
console.log(newPerson.__proto__ === Person.prototype) // true
console.log(Object.getPrototypeOf(newPerson) === Person.prototype) // true
```

# .__ proto __ & instanceof
![relationship4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2477698/c0b6db43-4bc5-8a41-45a8-04cf2d4e44fb.png)
**`instance`：インスタンス、複製先。
`instanceof`：インスタンスの複製元の検定演算子。**

実はJavaScriptでは、（undefinedとnull除いて）すべてのプリミティブとオブジェクトが`Function`のインスタンスです。
以下はその検証コードです。
```jsx
console.log(String instanceof Function) // true
console.log(Number instanceof Function) // true
console.log(BigInt instanceof Function) // true
console.log(Boolean instanceof Function) // true
console.log(Symbol instanceof Function) // true

console.log(undefined instanceof Function) // false
console.log(null instanceof Function) // false

console.log(Array instanceof Function) // true
console.log(Object instanceof Function) // true
console.log(Function instanceof Function) // true

console.log(Person instanceof Function) // true
console.log(newPerson instanceof Function) // false
```
この検証で分かったのは、プリミティブもオブジェクトもインスタンス経由でメソッドの継承関係が成り立つことです。
`Person`内部のメソッドが全て`newPerson`が継承していくように、これらも`Function`から組み込みメソッドを継承している。

`console.log(newPerson instanceof Function) // false`だとしても、そもそも`newPerson`は`Person`が`Function`から継承したメソッドを複製したので、`Function.prototype`を経由しなくても`Function`のメソッドが利用できます。

ここで分かったのは、`prototype`による継承と、`instance`による継承が違うやり方だけど同じ目的を達成したということです。

なぜそこまではっきり言えるのかな。
うーん、実はここまではただ自分が検証結果の整理です。
実際ほかのプリミティブで検証してみたら、
```jsx
function Person() { }
const newPerson = new Person()
console.log(newPerson.prototype) // undefined
console.log(newPerson.__proto__) // {}
console.log(newPerson.__proto__ === Person.prototype) // true
console.log(newPerson instanceof Person) // true

console.log(newPerson.constructor) // [Function: Person]


const str = '123'
console.log(str.prototype) // undefined
console.log(str.__proto__) // {}
console.log(str.__proto__ === String.prototype) // true
console.log(str instanceof String) // false

console.log(str.constructor) // [Function: String]
```
`newPerson`も`str`もインスタンス同士だから**ほぼ同じ**反応が出てきて
⇒　インスタンスには`prototype`が`undefined`とのこと、
⇒　`.__proto__`が存在し、それが**複製元のprototype**とのこと
確かに`str`は`String`のインスタンスではないけれど、`str`も`new`のように完全複製をしたわけでもなかったため、この結果もおかしくないと思います。

ただ一つお互いの継承関係が分かる決め手がありますが、それが`constructor`です。
**`constructor`：コンストラクタ、構築子、複製元を記録するオブジェクト。**
↑自分よがりの解釈ですが、実際MDNの説明では、
>constructor プロパティは、インスタンスオブジェクトを生成した Object のコンストラクター関数への参照を返します。なお、このプロパティの値は関数そのものへの参照であり、関数名を含んだ文字列ではありません。
[Object.prototype.constructor](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor)

**「インスタンスオブジェクトを生成した Object のコンストラクター関数への参照を返します。」**
確かに`constructor`は可変で自由に書き替えできますが、単にinitial valueから見るとおおむね両者の関係がわかるようになると思います。

↓はほかの検証です。
```jsx
const arr = []
console.log(arr.prototype) // undefined
console.log(arr.__proto__) // Object(0) []
console.log(arr.__proto__ === Array.prototype) // true
console.log(arr instanceof String) // false
console.log(arr.constructor) // [Function: Array]
```

# .__ proto __ & instanceof & prototype
![relationship5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2477698/cb79672a-f796-98a1-efb5-3fb8905c3876.png)
ここはプリミティブとオブジェクトの`prototype`がどんな感じしているのと、さきほど`instanceof`の参照と合わせた図です。

この図を理解すれば、もう`.__proto__`と`prototype`に振り回されることありません！（そう願います）

そして、もし`Function`に何か書き込んだらどうなるかな？詳しくは[おまけの検証コード](https://qiita.com/drafts/e1b7d59d9f406e73977b/edit#%E3%81%8A%E3%81%BE%E3%81%91%E3%81%AE%E6%A4%9C%E8%A8%BC%E3%82%B3%E3%83%BC%E3%83%89)へ。
実際、`Function`の`.__proto__`（参照先）、つまり`Function.prototype`を書き替えたらさらに大変なことになります。（低速の操作且つプロトタイプチェーンの破壊）
なので`.__proto__`の使用はお勧めしません。[[prototype]]を暴くには`Object.getPrototypeOf()`（read-only）などより安全なメソッドがあります。

↓は上の相関図の検証コードです。
```jsx
console.log(String.prototype) // {}
console.log(Number.prototype) // {}
console.log(BigInt.prototype) // Object [BigInt] {}
console.log(Boolean.prototype) // {}
// console.log(undefined.prototype)
// TypeError: Cannot read property 'prototype' of undefined
console.log(Symbol.prototype) // Object [Symbol] {}
// console.log(null.prototype)
// TypeError: Cannot read property 'prototype' of null
console.log(Array.prototype) // Object(0) []
console.log(Object.prototype) // [Object: null prototype] {}
console.log(Function.prototype) // {}

// is {} equal?
console.log(String.prototype === Number.prototype) // false
console.log(String.prototype === Boolean.prototype) // false
console.log(Number.prototype === Boolean.prototype) // false

console.log(String.prototype === Function.prototype) // false
console.log(Boolean.prototype === Function.prototype) // false
console.log(Number.prototype === Function.prototype) // false

// is anyone equal?
console.log(String.prototype === Function.prototype) // false
console.log(Number.prototype === Function.prototype) // false
console.log(BigInt.prototype === Function.prototype) // false
console.log(Boolean.prototype === Function.prototype) // false
console.log(Symbol.prototype === Function.prototype) // false

console.log(Array.prototype === Function.prototype) // false
console.log(Object.prototype === Function.prototype) // false
```

**7/15補足：**
Chrome DevToolの結果からみると、データ型それぞれのメソッドは各自の`prototype`に保存していると考えられます。
つまりプリミティブもオブジェクトも`Function`のインスタンスとして自分の`prototype`を形成し、自らのデータ型に使用できるメソッドをそこに保存するかもしれません。
しかしこれはプリミティブ、オブジェクトというデータ型に成り立つ話です。`new`で創られたインスタンスはこの機能がありません。`.prototype`は`undefined`です。
![dataprototype.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2477698/31384fc4-1b66-5b8e-b08b-f62d886c33ca.png)

# function & its prototype & `new` instance
![relationship6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2477698/fc7d5868-4871-8a47-27fd-4469b84b56c1.png)
ここに二つ疑問があります。
プリミティブなら元々存在して、複製元とのインスタンスの継承関係も分かったけど、
`Person`は私が勝手に創り出した関数ですよね？`str`と同じように`instanceof`が`false`を返すはずだが、なぜか`true`でした。
```jsx
console.log(Person instanceof Function) // true
```
また、`Person.prototype`が存在する時点が明らかに`Person`より前なんて不可能だと思います。ほかのプリミティブやオブジェクトはこの問題がないだが、`Function`と関わるとなんだか複雑になります。

自分の考察では、
一つ目は普通の関数は`Function`のインスタンスだから、インスタンスが**複製元のprototype**、つまり`Function.prototype`のメソッドを継承する、ここまでは`str`と同じように見えるが全然違うと思います。`instanceof`が`true`になったのは、関数`Person`が`Function`を完全複製したわけです。そのおかげで、関数には何でも入れられる、何でも利用できるオブジェクトになるのは、ほかのプリミティブやオブジェクト（`object`を除いて）ができないことです。

なぜまたそんなこと言いきれる？
だって`Object`も同じことやってるじゃん...。
```jsx
console.log(Object instanceof Function) // true
console.log(Function instanceof Object) // true
```
（**あくまでも考察からの自己解釈。**）

二つ目は述べたように`Person.prototype`が`Person`関数が創り出されると同時に生まれるが、`Function.prototype`と、その上の`Object.prototype`、`null`はその前の時点ですでに存在していると思います。（そうでないと継承関係ごじゃごじゃになるから）

# おまけの検証コード
```jsx
// constructor
console.log(String.constructor) // [Function: Function]
console.log(Number.constructor) // [Function: Function]
console.log(BigInt.constructor) // [Function: Function]
console.log(Boolean.constructor) // [Function: Function]
// console.log(undefined.constructor)
// TypeError: Cannot read property 'constructor' of undefined
console.log(Symbol.constructor) // [Function: Function]
// console.log(null.constructor)
//TypeError: Cannot read property 'constructor' of null

console.log(Array.constructor) // [Function: Function]
console.log(Object.constructor) // [Function: Function]
console.log(Function.constructor) // [Function: Function]

console.log(Person.constructor) // [Function: Function]
console.log(Person.prototype.constructor) // [Function: Person]
console.log(newPerson.constructor) // [Function: Person]

Function.constructor = Person

console.log(String.constructor)
// [Function: Function] { constructor: [Function: Person] }
console.log(Number.constructor)
// [Function: Function] { constructor: [Function: Person] }
console.log(BigInt.constructor)
// [Function: Function] { constructor: [Function: Person] }
console.log(Boolean.constructor)
// [Function: Function] { constructor: [Function: Person] }
console.log(Symbol.constructor)
// [Function: Function] { constructor: [Function: Person] }

console.log(Array.constructor)
// [Function: Function] { constructor: [Function: Person] }
console.log(Object.constructor)
// [Function: Function] { constructor: [Function: Person] }
console.log(Function.constructor)
// [Function: Person]

console.log(Person.constructor)
// [Function: Function] { constructor: [Function: Person] }
console.log(Person.prototype.constructor) // [Function: Person]
console.log(newPerson.constructor)
// [Function: Person]
```