【javaScript】prototypeとは？


<h1>prototypeとは</h1>
<h4>語源</h4>
製品開発を進めるうえで基本的な設計に問題がないかどうかを製品相当のテスト品を製造し、チェックしますが、プロトタイプとは、このときに製造されたプログラムの試作版のこと by Weblio辞書

<h4>javaScriptにおける意味</h4>
プロトタイプは、JavaScript オブジェクトが互いに機能を継承するメカニズム by MDN

<h1>書き方</h1>

まずはメソッドを持つオブジェクトを作る

```javascript
let User = function(name, age) {
  this.name = name;
  this.age = age;
  this.sayHi = function() {
    return `Hi, I'm ${this.name}`;
  };
}

let user = new User('John', 30);
console.log(user);
console.log(user.sayHi());


//コンソール
{ name: 'John', age: 30, sayHi: [Function (anonymous)] }
John
```

次にこれを prototype を用いてつくる

※prototype の書き方は
【 オブジェクト名.prototype.メソッド名= function() { } 】

```javascript
let User = function(name, age) {
  this.name = name;
  this.age = age;
}

User.prototype.sayHi = function () {
    return this.name
}

let user = new User('John', 30);
console.log(user);
console.log(user.sayHi());


//コンソール
{ name: 'John', age: 30 }
John
```

<h1>prototypeを使うメリット</h1>
２つの書き方の結果はほとんど同じである
が一か所違うところが

```javascript
//コンソール
{ name: 'John', age: 30, sayHi: [Function (anonymous)] }
//コンソール
{ name: 'John', age: 30 }
```

上の例ではインスタンス化するときにメソッドもコピーするのに対し、
下の例では、コピーされていない

つまり、prototype を使えば無駄なメモリの消費を抑えられる

<h3>prototypeはなぜメモリの消費を抑えられるのか</h3>

prototype を用いるとインスタンス化の際メソッドは参照して、用いられるからである

例えば、例のコンストラクタをそれぞれ５回ずつインスタンス化した場合

```javascript
//上の例
{ name: 'John', age: 30, sayHi: [Function (anonymous)] }
{ name: 'John', age: 30, sayHi: [Function (anonymous)] }
{ name: 'John', age: 30, sayHi: [Function (anonymous)] }
{ name: 'John', age: 30, sayHi: [Function (anonymous)] }
{ name: 'John', age: 30, sayHi: [Function (anonymous)] }
//下の例
{ name: 'John', age: 30 }
{ name: 'John', age: 30 }
{ name: 'John', age: 30 }
{ name: 'John', age: 30 }
{ name: 'John', age: 30 }

prototype
(sayHiメソッド)
```

このようなイメージになる
インスタンス化が多いほど protptype を使うメリットが大きくなる

試しに prototype の中を見てみると

```javascript
let User = function (name, age) {
  this.name = name;
  this.age = age;
};

User.prototype.sayHi = function () {
  return this.name;
};

let user = new User('John', 30);
console.log(User.prototype.sayHi);
console.log(User.prototype.sayHi());

//コンソール
[Function(anonymous)];
undefined;
```

メソッドである

```javascript
console.log(User.prototype.sayHi());
```

が undefined なのはインスタンス化していないので this.name が undefined のためである

<h1>「prototype」による継承</h1>

<h3>プロトタイプチェーン</h3>
中身が空のオブジェクトを３っつ用意します

```javascript
let soccerPlayer = function () {};
let baseballPlayer = function () {};
let doctor = function () {};
```

この 3 つのオブジェクトがそれぞれ持っている「プロトタイプ」を連結させるには
各プロトタイプには連結させたいオブジェクトのインスタンスを代入する

つまり

```javascript
baseballPlayer.prototype = new soccerPlayer();
```

「baseballPlayer」と「soccerPlayer」のプロトタイプはそれぞれ参照できる状態である

そしてこうすることで

```javascript
doctor.prototype = new baseballPlayer();
```

【soccerPlayer】【baseballPlayer】【doctor】
がそれぞれ繋がったわけでである

<h3>継承</h3>

```javascript
let soccerPlayer = function () {};
let baseballPlayer = function () {};

soccerPlayer.prototype.kick = function () {
  return 'kick';
};

baseballPlayer.prototype = new soccerPlayer();

let human1 = new soccerPlayer();
let human2 = new baseballPlayer();

console.log(human1.kick());
console.log(human2.kick());

//コンソール
kick;
kick;
```

baseballPlayer の prototype は soccerPlayer の prototype を継承しているので kick メソッドが使えるわけである