JavaScript: プロトタイプチェーンにおけるプロパティ探索の順序

## アジェンダ
プロトタイプチェーンにおけるプロパティ探索の順序について簡単にまとめます。

## プロパティ探索の順序

1. **オブジェクト自身のプロパティ**: 
まず、オブジェクト自身が持っているプロパティが参照されます。もしそのプロパティが存在する場合は、その値が返されます。

2. **オブジェクトのプロトタイプ (`__proto__`)**:
2オブジェクト自身に該当するプロパティがない場合、そのオブジェクトのプロトタイプオブジェクトが参照されます。このプロトタイプオブジェクトもまたオブジェクトであり、同じ手順でプロパティが探されます。

3. **プロトタイプチェーンの遡り**:
プロトタイプオブジェクトにも該当するプロパティがない場合、そのプロトタイプオブジェクトのプロトタイプ（つまり、プロトタイプのプロトタイプ）が参照されます。これが繰り返され、チェーンを辿っていきます。

4. **最上位の `Object.prototype`**:
最終的に、すべてのオブジェクトは `Object.prototype` に辿り着きます。`Object.prototype` には標準的なJavaScriptのオブジェクトが共通で持つメソッドやプロパティ（`toString()`、`hasOwnProperty()` など）が定義されています。

5. **`null`**:
プロトタイプチェーンの最上位は `null` で、`null` に達するとそれ以上プロトタイプチェーンを遡ることはできません。もし参照するプロパティがチェーン内のどのオブジェクトにも存在しない場合は、`undefined` が返されます。

このように、プロトタイプチェーンはオブジェクト自身から始まり、順次プロトタイプを遡りながら該当するプロパティを探していく仕組みです。

## 実例:
先ほどの1から5の流れを実感するために、実例として以下の様なコードがあるとします。
このコードでは、`Person` コンストラクタ関数を定義し、そのプロトタイプに `greet` メソッドを追加しています。`john` は `Person` のインスタンスです。

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

Person.prototype.greet = function() {
    return `Hello, my name is ${this.name}`;
};

const john = new Person('John');
```

では、上記`john` オブジェクトを活用してプロパティやメソッドがどのように参照されるかを確認していきます。

### 1. **オブジェクト自身のプロパティ**
```javascript
console.log(john.name); // 'John'
```
ここでは、`john` オブジェクトに直接 `name` プロパティが存在するため、`John` が返されます。

### 2. **オブジェクトのプロトタイプ (`__proto__`)**
```javascript
console.log(john.greet()); // 'Hello, my name is John'
```
`john` オブジェクトには `greet` プロパティが存在しないため、`Person.prototype` にある `greet` メソッドが参照され、実行されます。

### 3. **プロトタイプチェーンの遡り**
```javascript
console.log(john.toString()); // '[object Object]'
```
`toString` メソッドは `john` オブジェクトにも `Person.prototype` にも存在しませんが、`Person.prototype` のプロトタイプである `Object.prototype` に定義されています。したがって、`Object.prototype.toString` メソッドが実行されます。

### 4. **最上位の `Object.prototype`**
```javascript
console.log(john.hasOwnProperty('name')); // true
```

`hasOwnProperty` メソッドも `Object.prototype` に存在します。`john` オブジェクトには直接存在しませんが、プロトタイプチェーンを遡って `Object.prototype.hasOwnProperty` メソッドが呼び出されます。

### 5. **`null`**
プロトタイプチェーンの最後は `null` に到達します。もし参照しているプロパティが `Object.prototype` にも存在しなければ、`undefined` が返されます。
   
```javascript
console.log(john.nonExistentProperty); // undefined
```

### johnオブジェクトを展開
`john` オブジェクトを展開すると、以下のような形で表示されます。
これはオブジェクトの各プロパティとそのプロトタイプチェーンの構造を示します。

```javascript
{
  name: 'John',
  __proto__: {
    greet: function() { return `Hello, my name is ${this.name}`; },
    __proto__: {
      // Object.prototype のプロパティとメソッド
      constructor: function Object() { ... },
      hasOwnProperty: function hasOwnProperty() { ... },
      isPrototypeOf: function isPrototypeOf() { ... },
      propertyIsEnumerable: function propertyIsEnumerable() { ... },
      toString: function toString() { ... },
      valueOf: function valueOf() { ... },
      // さらに他の Object.prototype のプロパティ
      __proto__: null
    }
  }
}
```

1. **`name: 'John'`**:
   - `john` オブジェクトに直接定義されているプロパティです。

2. **`__proto__`**:
   - `john` オブジェクトのプロトタイプ (`Person.prototype`) への参照です。ここに `greet` メソッドが定義されています。

3. **`Person.prototype` の `__proto__`**:
   - `Person.prototype` のプロトタイプは `Object.prototype` です。ここには `constructor` や `toString` などの標準的なJavaScriptのオブジェクトに共通のプロパティやメソッドが定義されています。

4. **`Object.prototype` の `__proto__`**:
   - `Object.prototype` のプロトタイプは `null` です。これはプロトタイプチェーンの最上位であり、これ以上遡ることはありません。

## まとめ
プロパティが見つかるまでプロトタイプチェーンを順番に遡ることで、JavaScriptは適切なプロパティやメソッドを見つけ出します。
## 参考
- [図で理解するJavaScriptのプロトタイプチェーン #Node.js - Qiita](https://qiita.com/howdy39/items/35729490b024ca295d6c)