JS初心者の自分がつまづいた、「プロトタイプベースのオブジェクト指向」について調べてみた

# 概要

JavaScript初心者だった私が、 [『改訂新版JavaScript本格入門』](https://www.amazon.co.jp/%E6%94%B9%E8%A8%82%E6%96%B0%E7%89%88JavaScript%E6%9C%AC%E6%A0%BC%E5%85%A5%E9%96%80-%E3%83%A2%E3%83%80%E3%83%B3%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%AB%E3%81%AB%E3%82%88%E3%82%8B%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E7%8F%BE%E5%A0%B4%E3%81%A7%E3%81%AE%E5%BF%9C%E7%94%A8%E3%81%BE%E3%81%A7-%E5%B1%B1%E7%94%B0-%E7%A5%A5%E5%AF%9B/dp/477418411X)にあたり、
つまづいた「プロトタイプベースのオブジェクト指向」を調べてみました。

# 留意点

* あくまで「調べてみた」なので、完璧に理解できているわけではありません
* いろんなものを調べた結果、どう自分は理解したかを書いていきます
* 様々な本や記事を参考にしました(できる限りリンクを貼ったつもりです)
* 皆様の解釈と異なるかもしれませんが、多めに見てください(明らかに違う場合はご指摘お願いします)

# この記事を書いた人間の状況(2019/5 現在)

* PHPを中心に開発してきました(書いた時で3年半くらい)
* クラスベースのオブジェクト指向はある程度理解しているつもりです
* JavaScript(JS)は正直本格的にやってこなかったため、勉強をはじめました
* 『改訂新版JavaScript本格入門』 の「プロトタイプベース」という言葉に馴染みがなく、つまづきました
* なので調べてみた、というのが今回の記事です

# 本題

以下の通りです。

1. そもそもオブジェクト指向とは？
2. プロトタイプベースはクラスタイプベースとどう違うのか？
3. プロトタイプベースでは、(クラスベースと違って)何ができるの？
4. プロトタイプベースは今後どうなるのか？

## 1. そもそもオブジェクト指向とは？

* これだけでご飯３杯はいける内容です(のでここでは割愛)
* 個人的には[『オブジェクト指向でなぜつくるのか』](https://www.amazon.co.jp/%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E6%8C%87%E5%90%91%E3%81%A7%E3%81%AA%E3%81%9C%E3%81%A4%E3%81%8F%E3%82%8B%E3%81%AE%E3%81%8B-%E7%AC%AC2%E7%89%88-%E5%B9%B3%E6%BE%A4-%E7%AB%A0/dp/4822284654) という書籍がおすすめです
* Qiitaだと、 [オブジェクト指向と10年戦ってわかったこと](https://qiita.com/tutinoco/items/6952b01e5fc38914ec4e) や [オブジェクト指向のいろは](https://qiita.com/nrslib/items/73bf176147192c402049) が有名です(私も勉強させていただきました)
* 私の解釈としては、「オブジェクト指向で実装すると、コードの重複を防いで修正漏れを無くしてくれたり、コードを一文一文全て読まなくても、メソッドとプロパティでどういうことができるかを理解できたり、他のオブジェクトとの結合箇所だけ注意すればバグが起こりにくかったり・・・と言った(手続き型と比べて)利点がたくさんあるよね」と思っています(なげえよ)

## 2. プロトタイプベースはクラスタイプベースとどう違うのか？

[Javascriptでオブジェクト指向するときに覚えておくべきこと](https://qiita.com/awakia/items/8ff451ca5f8ae0122be7) という記事に、以下の通り書かれていました

> クラスベース (Java):クラスとインスタンスは異なる実体です。
> プロトタイプベース (JavaScript):すべてのオブジェクトはインスタンスです。

『改訂新版JavaScript本格入門』にも似た話が記載されていました。
「クラスという名の抽象的な設計図(雛形)がなくて、すべては実体なんだなー」と私は理解しました。
(ES6から[クラスの概念](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Classes)が導入されたことは、話がややこしくなるので一旦ここでは無視しています)

## 3. プロトタイプベースでは、(クラスベースと違って)何ができるの？

ここが特に興味深いところでした。まだまだあるかもしれませんが、以下の2点が書かれていました。

* インスタンスにプロパティを追加・削除ができる(関数リテラルも対象なので、メソッドも追加できる)
* prototypeプロパティを使って、全てのオブジェクトの元になるプロトタイプオブジェクトにメソッドを追加し、さらにそれを別のインスタンスから参照することができる

※2019/5/25 以下追記
↓↓↓↓↓
こちらコメントにてご指摘をいただいた通り、オープンクラスを採用している言語では、
既存のクラスにメソッド等を追加が可能とのことでした。
あくまでこのクラスベースとは「インスタンスにメソッド等を追加できない」言語を対象にしています。
↑↑↑↑↑

この「できる」は、非常に「怖い」なあと私は思ってしまいました。
「このオブジェクトはこのメソッドが定義されているから使えるはず」
「このオブジェクトで何ができるのかは定義(クラス)を見にいけばいい」
というのが一切通用しなくなるわけですから、ソースコードを注意深く読まなければいけません。
(もっとも`seal`メソッドを使うなど、その辺りの懸念を低減するものもあるとのことですが)

またこういったインスタンスにプロパティを追加/削除できるというのが、
「JSのオブジェクトは連想配列みたいなもん」と言われる所以なんだろうなあと思いました。

## 4. プロトタイプベースは今後どうなるのか？

あくまで私の感想ですが、プロトタイプベースで今後JSを書くのは少なくなると感じています。

実際先ほど触れた通りES6からクラスの概念が導入され、
またTypeScriptなどAltJSで他の言語と同じように、クラスベースで簡単に書くことができます。

そもそもバックエンド側のメジャーな言語は、クラスベースのオブジェクト指向が使われていることからも、
馴染みの薄いプロトタイプベースで実装する理由はあまり見つかりません。

ただだからと言って、プロトタイプベースを理解しなくていいというわけにはいかないとも思っています。
上記事項を理解してないと、既存のソースコードがわかりにくい可能性が高いです。(実際私はここでつまづきました)

特にクラスに精通している方こそ、「なんでインスタンスにメソッド追加してるの？」とか思ってしまうかもしれません。
そうではなく「JSではこういう書き方もできるんだ」と覚えておいても損ではないかなあ、と思っています。

# 参考にした書籍、リンク

[『改訂新版JavaScript本格入門』](https://www.amazon.co.jp/%E6%94%B9%E8%A8%82%E6%96%B0%E7%89%88JavaScript%E6%9C%AC%E6%A0%BC%E5%85%A5%E9%96%80-%E3%83%A2%E3%83%80%E3%83%B3%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%AB%E3%81%AB%E3%82%88%E3%82%8B%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E7%8F%BE%E5%A0%B4%E3%81%A7%E3%81%AE%E5%BF%9C%E7%94%A8%E3%81%BE%E3%81%A7-%E5%B1%B1%E7%94%B0-%E7%A5%A5%E5%AF%9B/dp/477418411X)のChapter 5
[Javascriptでオブジェクト指向するときに覚えておくべきこと](https://qiita.com/awakia/items/8ff451ca5f8ae0122be7)
[クラスベースとプロトタイプベース](https://prime503.hatenadiary.org/entry/20091225/1261720985)
[JavaScriptをプロトタイプベースのオブジェクト指向言語と言うべきではない](http://blog.anatoo.jp/entry/2015/05/05/163225)