JavaScriptはプロトタイプベースのオブジェクト指向プログラミング言語ではない!?

先日のブログ記事に、たくさんのブックマークをいただきました。

どうもありがとうございます★★★

ブックマークのコメントで、こんな意見がありました。

オブジェクト指向って便利なの? – JavaScript勉強会

うへええええ継承による差分プログラミングとか現代に言わないでくれよ。しかも「JSはプロトタイプベースのOOP」を初めとして間違いが多いぞ

2017/03/27 09:42

なるほど、そういう見方もあるんですね?(参考になります)

(1) 継承による差分プログラミングは、現代では廃れた古い手法?

(2) JavaScriptはプロトタイプベースのオブジェクト指向プログラミング言語ではない?

実際のところ、どうなんでしょうか?

知識は知識として、正確に理解しておきたいです。

勉強がてら、調べてみましょう。

とりあえず、(2)のプロトタイプベースの方から先に見てみることにします。

ちなみに、英語の「prototype」は、日本語で「原型」という意味です。

(「proto」は「最初の、原始の」、「type」は「型、形式」という意味です。)

Wikipediaの説明

JavaScript – Wikipedia

JavaScriptとは、プログラミング言語のひとつである。

一般的に、プロトタイプベースのオブジェクト指向スクリプト言語であると言われている。

しかし、コンストラクタなどのクラスベースに見られる機能も取り込んでいる。

JavaScript – Wikipedia

JavaScript is a high-level, dynamic, untyped, and interpreted programming language.

It has been standardized in the ECMAScript language specification.

Alongside HTML and CSS, JavaScript is one of the three core technologies of World Wide Web content production; the majority of websites employ it, and all modern Web browsers support it without the need for plug-ins.

JavaScript is prototype-based with first-class functions, making it a multi-paradigm language, supporting object-oriented, imperative, and functional programming styles.

プロトタイプベース – Wikipedia

プロトタイプベースとは、オブジェクト指向言語と総称されるプログラミング言語のうち、プロトタイプを基礎(ベース)としてオブジェクトを取り扱うものをいう。インスタンスベースとも。

一方、オブジェクトの取り扱いをクラスでおこなっているものをクラスベースとよぶ。

プロトタイプベースのオブジェクト指向言語は一般的なオブジェクト指向言語とは対照的に、静的なクラスを持たず、新しいオブジェクトを既存のオブジェクトのクローンから作成する。

Smalltalkを元にクラスの複雑性を排除したSelfが特に有名である。

他にJavaScript、NewtonScript、Ioなどがプロトタイプベース(またはその機能を持つ)と考えられる。

Prototype-based programming – Wikipedia

Prototype-based programming is a style of object-oriented programming in which behaviour reuse (known as inheritance) is performed via a process of reusing existing objects via delegation that serve as prototypes.

This model can also be known as prototypal, prototype-oriented, classless, or instance-based programming.

Delegation is the language feature that supports prototype-based programming.

The first prototype-oriented programming language was Self, developed by David Ungar and Randall Smith in the mid-1980s to research topics in object-oriented language design.

Since the late 1990s, the classless paradigm has grown increasingly popular.

Some current prototype-oriented languages are JavaScript (and other ECMAScript implementations, JScript and Flash’s ActionScript 1.0), Lua, Cecil, NewtonScript, Io, Ioke, MOO, REBOL, Lisaac and AHk.

Wikipediaの説明では、

「JavaScriptはプロトタイプベースのオブジェクト指向プログラミング言語」

という説明になっていました。

これは、広く知れ渡っているJavaScriptの一般的な説明であり、多くのプログラマーが目にしている情報でしょう。

Mozillaの説明

JavaScriptを開発しているMozillaの説明は、どうなっているでしょうか?

JavaScript プロトタイプベース Mozilla – Google 検索

MDNのJavaScriptリファレンス(学習や実務で役立つ情報が提供されています。)

MDNの説明を見てみましょう。

JavaScript は、クラスではなく、プロトタイプに基づいたオブジェクトベースの言語です。

「プロトタイプベース」とは別に「オブジェクトベース」という用語も出てきました。(後で詳述)

クラスベース言語とプロトタイプベース言語

Java や C++ といったクラスベースのオブジェクト指向言語は、クラスとインスタンスという 2 種類の異なる実体があるという概念に基づいています。

  • クラスは、あるオブジェクトの集まりを特徴付けるすべてのプロパティ(Java ではメソッドとフィールドを、C++ ではメンバをプロパティとみなします)を定義します。クラスとは、自身を表すオブジェクト集合のメンバよりも、より抽象的なものです。例えば、Employee クラスは従業員すべての集合を表現することができます。
  • 一方、インスタンスはクラスを具体化したものです。つまり、クラスのメンバの 1 つです。例えば、Victoria は Employee クラスのインスタンスになることができます。このインスタンスは、特定の個人を従業員として表すものです。インスタンスは、その親クラスのプロパティを(過不足なく)正確に保持します。

JavaScript のようなプロトタイプベースの言語は、この区別がありません。単にオブジェクトがあるだけです。プロトタイプベース言語には、プロトタイプオブジェクト (prototypical object) という概念があります。このオブジェクトは、新しいオブジェクトの初期プロパティの取得元になるテンプレートとして使用されます。どのオブジェクトも独自のプロパティを指定できます。これはオブジェクト作成時にも実行時にも可能です。さらに、どのオブジェクトも別のオブジェクトに対するプロトタイプとして関連づけることができます。2 つ目のオブジェクトに対し 1 つ目のオブジェクトのプロパティを共有させることもできます。

JavaScriptの開発元であるMozillaの説明によると、JavaScriptは、

  • クラスベースのオブジェクト指向プログラミング言語ではなく、
  • プロトタイプベースのオブジェクト指向プログラミング言語である

とのことです。

developer.mozilla.org

プロトタイプベースプログラミング

プロトタイプベースのプログラミングはクラスを使用せず、既存のプロトタイプオブジェクトをデコレート(あるいは拡張)してそのオブジェクトの持つ挙動を再利用する(クラスベースの言語における継承と同等)ことで実現される OOP モデルです(クラスレス、プロトタイプ指向、あるいはインスタンスベースプログラミングとも呼ばれます)。

プロトタイプベース言語として先駆けの(そしてもっとも正統な)代表例は、David Ungar 氏と Randall Smith 氏によって開発された Self です。とはいえ、クラスレスのプログラミングスタイルは最近ますます人気が高まり、JavaScript、Cecil、NewtonScript、Io、MOO、REBOL、Kevo、Squeak (ソフトウェア Morphic のコンポーネント操作の際の Viewer フレームワークとして使われています)などのプログラミング言語に採用されました。

「プロトタイプベース」とは別に「インスタンスベース」という用語も出てきました。(後で詳述)

クラス

JavaScript はプロトタイプベースの言語であり、C++ や Java でみられる class 文がありません。これは時に、class 文を持つ言語に慣れているプログラマを混乱させます。

JavaScriptは、プロトタイプベースの言語、とのこと。

概要

JavaScript はオブジェクト指向の動的言語であり、型や演算子、標準組み込みオブジェクト、メソッドがあります。その構文は Java や C 言語に由来するので、それらの言語の多くの構造が JavaScript にも同様に適用できます。重要な違いのひとつに、JavaScript にはクラスがありません。その代わり、クラスの機能はオブジェクトプロトタイプによって達成されています (詳しくは ES6 の Classes をご覧ください)。

  • JavaScriptにはプロトタイプがある。
  • JavaScriptにはクラスがない。
  • (ES6でクラスの糖衣構文が用意された)

ECMAScript 6 で導入された JavaScript クラスは、JavaScript にすでにあるプロトタイプベース継承の糖衣構文です。

クラス構文は、新しいオブジェクト指向継承モデルを JavaScript に導入しているわけではありません。

JavaScript クラスは、オブジェクトを作成して継承を扱うためのシンプルで明確な構文を用意します。

  • ES6(ECMAScript 6)で導入された「クラス」は、ES5のプロトタイプベースを基にして作った「糖衣構文」(シンタックスシュガー)とのこと。
  • ES6になっても、厳密には、JavaScriptがクラスベースのオブジェクト指向プログラミング言語に変わったわけではない。

(参考)糖衣構文 – Wikipedia

糖衣構文(とういこうぶん、syntactic sugar)は、プログラミング言語において、読み書きのしやすさのために導入される書き方であり、複雑でわかりにくい書き方と全く同じ意味になるものを、よりシンプルでわかりやすい書き方で書くことができるもののことである。構文上の書換えとして定義できるものであるとも言える。

糖衣構文はプログラムの意味としては同じものを、よりわかりやすい構文で書けるものである。

MDNの説明を見ると、JavaScriptのオブジェクト指向は、クラスベースではなくプロトタイプベースと定義されていることが分かりました。

f:id:jsstudy:20170329175139j:plain

(via 最強オブジェクト指向言語 JavaScript 再入門!) Published on Jul 1, 2013

現時点での認識

私のJavaScriptに関する知識はES5で止まっており、ES6(ES2015)以降の新しい知識はほとんどありません。現時点では以下のように認識しています。

  • ES5以前のJS:プロトタイプベースのOOPが可能
  • ES6以降のJS:クラスベースのOOPも可能

(A) JavaScript(ECMA Script)は、徐々にバージョンアップして、言語仕様が変わってきている。

(B) ES5以前のJSは、プロトタイプベースのOOPだった。クラスベースのOOPをエミュレートするために、一時期「Prototype.js」というライブラリーが流行っていた。

(C) ES6以降のJSでは、class構文が導入されて、クラスベースのOOPも可能になった。

(D) 現状では、後方互換性を保つためにトランスパイラーを使い、ES6からES5へダウンコンパイルして使うケースが多い。

(E) レガシーコードをメンテナンスする際には、まだES5の知識が必要。

(A) JavaScript(ECMA Script)のバージョン

JavaScriptの言語仕様は、現在ECMAScriptとして策定(標準化)されています。

→ 入門編 – JavaScript | MDNJavaScript と ECMAScript 仕様

JavaScript は国際的なプログラミング言語を提供できるように Ecma International によって標準化されています (ECMA は、以前は European Computer Manufacturers Association の頭文字をとったものでした)。

ECMAScriptの仕様策定に関するカンニングペーパー | Web Scratch

ECMAScriptとは?

Ecma Internationalによって標準化されてるJavaScriptの仕様の事。

仕様: ECMAScript

実装: JavaScript

JavaScriptの歴史

Javascriptの歴史 – Qiita

1997年 標準化へ

JscriptとJavascriptというブラウザ互換性のない状態を解決しようとNN社は,Javascriptを標準化しようと画策し,ECMAという標準化機関にJavascriptの標準化を依頼.

ECMA-262 初版ができる.

JavaScript の新機能 – JavaScript | MDN

このページはJavaScriptバージョン履歴の情報とFirefoxのようなMozilla/SpiderMonkeyベースのJavaScriptアプリケーションの実装状況を表示します。

  • ECMAScript versions
  • JavaScript versions

JavaScript 1.0 から 1.9 までの歴史

JavaScript – Wikipediaバージョンとブラウザの対応表

ECMAScript 5(ES5)以降の歴史

ECMAScript – Wikipedia バージョン

バージョンの命名則

「ES6」(ECMA Script 6)は正式名を「ES2015」(ECMA Script 2015)と言います。

以降ナンバリングの規則が変わり、ES2016、ES2017…となっています。

ECMA Scriptの言語仕様

JavaScriptの言語仕様は公開されているので、誰でも確認できます。

Ecma Standards – list (一覧)

Standard ECMA-262 (最新のバージョン)

ECMAScript 2017 Language Specification (次期バージョン:ES2017)

使用するJavaScriptのバージョン、実装によって、多少文法が異なるので注意が必要です。

(B) ES5以前のJS

ES5以前のJSは、プロトタイプベースのOOPであり、クラスベースのOOPではありませんでした。

JSでクラスベースのOOPをエミュレートするために、「Prototype.js」というライブラリーも登場しました。

Prototype JavaScript framework: a foundation for ambitious web applications

prototype.jsって・・・・なに? – /var/www/yatta47.log

Prototype JavaScript Framework – Wikipedia

特徴

Prototypeはクラス群とクラスベースのオブジェクトのためのライブラリ関数も提供する。これはJavaScript言語にはない部分である。

Prototype.jsはRuby on Railsにも採用されるなど、広く使われていました。

(その後、jQueryの登場によってPrototype.jsの人気は下火になりました。)

(C) ES6以降のJS

ES6(ES2015)で、JSにclassの糖衣構文が導入され、クラスベースのスタイルでOOPが可能になりました。

モダンブラウザーは、ES6に対応しているものが増えてきましたが、まだ後方互換性を完全に無視できるほどのシェアには達していないようです。(時間の問題?)

はてなブックマークやQiitaで、ES6(ES2015)の記事をザッピングしてみましょう。

本文「ES6」を検索 – はてなブックマーク (500 users 以上)

本文「ES2015」を検索 – はてなブックマーク (500 users 以上)

Qiitaに解説記事がたくさんありました。 概要の把握に役立ちます。

ES2015 (ES6)についてのまとめ – Qiita (2016年01月16日に投稿)

春からはじめるモダンJavaScript / ES2015 – Qiita (2016年07月12日に更新)

ES2015で始めるJavaScript入門 – Qiita (2016年09月26日に更新)

ES2015新機能: JavaScriptのclassとmethod – Qiita (2016年11月20日に更新)

ES2015(ES6) 入門 – Qiita (2016年12月16日に更新)

(D) JSのダウンコンパイル

現状では、ES6で書いたコードをES5で動くようにするために、Babel等のトランスパイラーを使い、ES6からES5へダウンコンパイルして使うケースが多いようです。

babeljs.io

(参考)モジュール分割、ビルド、コンパイルなどの作業フローまとめ

レトロエンジニアのための近代Webフロントエンド事情 – Qiita (2016年12月12日に更新)

トランスパイル (transpile)

ある言語で書いたソースコードを別の言語のそれに変換する機能。

この機能をもつものをトランスパイラという。

コンパイラがソースコードを吸ってバイナリを吐くのと同じように、スクリプト言語界では、トランスパイラがソースコードを吸ってソースコードを吐く。

Closure Compiler が ES6 のキャッチアップを開始 – latest log

【Angular2入門】TypeScriptをコンパイルからのWatchifyでファイル結合、ブラウザで動作確認するところまで – Gulpで作るwebフロントエンド開発環境 – NET BIZ DIV. TECH BLOG

JSは、もはやインタープリター言語じゃなくてコンパイル言語になってますね!?

今後のトレンド予想

ES6→ES5=JSをJSで書いてコンパイルって、面倒くさくないですか?

どうせコンパイルするなら、他の言語でもOKという動きが活発になるのでは?

  1. 超強力なIDEが登場して、ES6を書いたら即座にES5を吐き出してくれる。
  2. 他の言語をJSにトランスパイルする。(例:Haxe)
  3. WebAssembly / asm.jsで、他の言語がJSの代わりに使えるようになる。

とか、他の代替手段も発展していきそうな気がします。(期待)

haxe.org

WebAssembly – Wikipedia

WebAssemblyは、ウェブブラウザのクライアントサイドスクリプトとして動作するプログラミング言語(低水準言語)である。wasmとも称されており、ブラウザ上でバイナリフォーマットの形で実行可能であることを特徴とする。

2016/05/11時点でWebAssembly関連の情報を整理してみた – Qiita

WebAssembly事始め(Chrome57記念) – Qiita

便利なツールを作成~オープンソースで提供してくださる方々に感謝ですね!

(E) JSのレガシーコード

ES5で作られているサイトは、まだまだ多いと思います。

メンテナンスする際には、まだES5の知識が必要ですよね?

以上、ざっとJSの現状、今後のトレンドを眺めたところで、本題に戻りましょう。

プロトタイプベース以外の別名

JSのオブジェクト指向について調べてみると、

  • クラスベース
  • プロトタイプベース

の他に、

  • オブジェクトベース
  • インスタンスベース

という用語、名称も出てきました。

これらの名称には、クラスベースとの違いを明示する以上に、何か特別な意味があるのでしょうか?

検索したら参考になる記事がヒットしました。

順番に見ていきましょう。

「インスタンスベース」という用語の定義は?

プロトタイプベースの誤解 – Smalltalkのtは小文字です

個人的には、クラスを用いないオブジェクト生成手法の話でないのならば(つまり、「プロトタイプの複製でオブジェクトを生成する」ことが話の本筋でないならば)「プロトタイプベース」ではなく、「インスタンスベース」(あるいは「オブジェクトベース」…)と言い換えることを推奨しています。

  • クラスベースのOOP → クラスをインスタンス化してオブジェクトを作成。
  • 非クラスベースのOOP → いろいろなオブジェクトの作り方がある。
    一例として、プロトタイプベースのOOPなら、プロトタイプをクローン(コピー)してオブジェクトを作成。

議論領域の分割方法として、「クラスベース」と「非クラスベース」の2項対立では、説明できない部分(OOPの特徴)が出てくるんですね。

→ 誤った二分法 – Wikipedia

誤った二分法(false dichotomy)あるいは誤ったジレンマ(false dilemma)は非論理的誤謬の一種であり、実際には他にも選択肢があるのに、二つの選択肢だけしか考慮しない状況を指す。

2つより多い選択肢の一覧が示され、その一覧以外の選択肢が存在するのに考慮しない場合、これを誤った選択の誤謬 (fallacy of false choice) または網羅的仮説の誤謬 (fallacy of exhaustive hypotheses) と呼ぶ。

では、どんな分類がより適切なのでしょうか?

最近は説明が面倒で「プロトタイプベース」で通してしまうことも多いのですが…反省。

#ちなみに「インスタンスベース」や「オブジェクトベース」というのは、別に私の造語というわけではなく、論文や書籍などで比較的古くから使われている用語です。

OOPの仕組みを細分化して、名前を付け、説明方法を改善することは可能?

繰り返しになりますが念のため。オブジェクトがそれが属するクラスによらず独自のメソッドやインスタンス変数を持てること*こそ*が、「プロトタイプベース」あらため「インスタンスベース」の本質です。

議論の対象が、

  • 作る前:オブジェクトの生成方法

ではなく、

  • 作った後:オブジェクトの性質

に焦点が当てられています。

言語デザインにおいて、生成方法と性質の間に依存関係がなければ、両者は直交した概念として、別々に検討できるでしょう。

ここでは、オブジェクトの「性質」(振る舞い)に着目して、オブジェクトのメンバー(プロパティーやメソッド)が動的に変更(追加/削除)できる、という性質が「インスタンスベース」の持つ特徴であると定義すれば良いのでしょうか?

ここで、「第1級オブジェクト」、「第1級関数」について確認しましょう。

第一級オブジェクト – Wikipedia

第一級オブジェクト(ファーストクラスオブジェクト、first-class object)は、あるプログラミング言語において、たとえば生成、代入、演算、(引数・戻り値としての)受け渡しといったその言語における基本的な操作を制限なしに使用できる対象のことである。ここで「オブジェクト」とは広く対象物・客体を意味し、必ずしもオブジェクト指向プログラミングにおけるオブジェクトを意味しない。第一級オブジェクトは「第一級データ型に属す」という。

言語によって異なるが、第一級オブジェクトは概ね次のような性質をもつ。

  • 無名のリテラルとして表現可能である。
  • 変数に格納可能である。
  • データ構造に格納可能である。
  • それ自体が独自に存在できる(名前とは独立している)。
  • 他のものとの等値性の比較が可能である。
  • プロシージャや関数のパラメータとして渡すことができる。
  • プロシージャや関数の戻り値として返すことができる。
  • 実行時に構築可能である。
  • 表示可能である。
  • 読み込むことができる。
  • 分散したプロセス間で転送することができる。
  • 実行中のプロセスの外に保存することができる。

第一級関数 – Wikipedia

計算機科学において、第一級関数(first-class function、ファーストクラスファンクション)とは、関数を第一級オブジェクトとして扱うことのできるプログラミング言語の性質、またはそのような関数のことである。

その場合その関数は、型のある言語では function type などと呼ばれる型を持ち、またその値は関数オブジェクトなどになる。

具体的にはプログラムの実行時に生成され、データ構造に含めることができ、他の関数の引数として渡したり、戻り値として返したりすることのできる関数をいう。

JavaScriptの関数は第1級オブジェクトなので、変数に代入したり、配列にセットしたり、他の関数に引き渡したりできます。つまり、関数をデータとして扱うことが可能です。

JavaScriptのオブジェクトは、連想配列と同じ構造です。(JSの連想配列はオブジェクトの一種?)

連想配列の要素(箱)をどんどん増やして、その中にデータや関数を入れられるように、オブジェクトのメンバーを増やしてプロパティー(データ)やメソッド(関数)を追加できます。

JavaScriptのオブジェクトのメンバーは、クラス(設計図)に依存しておらず、自由に追加削除できると。

なお、JavaScriptのオブジェクトの性質については、今後JavaScriptのリフレクションの作法を学習してから、より具体的に見てみたいと思います。

JavaScript リフレクション – Google 検索

→ リフレクション (情報工学) – Wikipedia

情報工学においてリフレクション (reflection) とは、プログラムの実行過程でプログラム自身の構造を読み取ったり書き換えたりする技術のことを指す。日本語では自己言及と呼ばれる。

一般に、リフレクションとはオブジェクトがそれ自身の構造や計算上の意味を取得することを可能にするものである。

JavaScript

インスタンスベースの性質や定義について、さらに見てみましょう。

「プロトタイプベース」というと(それを世に広めた SELF の影響で)「クラスがない」と短絡する人が多いのも問題のひとつです。

そうした偏った思いこみを払拭するのにも「インスタンスベース」との言い換えは有効だと思います。

オブジェクトが独自のスロットを持てることと、そのオブジェクトがクラスに属することは矛盾しない、つまりインスタンスベースの言語でもクラスを持つことはできるし、逆に、クラスベース言語でも(その言語がクラスベースにおいて純粋さを目指さない限りにおいて…)そのオブジェクトにインスタンスベース的素養を持たせることは可能です。

実際、完全なインスタンスベースの言語(NewtonScript、JavaScript、ActionScript)にクラスがあってもまったく問題はないわけですし、クラスベースの言語(Ruby、Python)であっても、オブジェクトがインスタンスベース的素養を持つ例はめずらしくありません。

  • インスタンスベースで、オブジェクトがクラスに属してもOK
  • 「型クラス」でオブジェクトを扱うことができる?

データ型と型クラスの違い – ushumpei’s blog

  • データ型:データ構造を定義するもの
  • 型クラス:振る舞いを定義するもの

JavaScript による型クラスの表現 · GitHub

型クラスとは

型が値の種類を表すとしたら, 型クラスは型の種類を表すようなものです.

例えば, ある型 (オブジェクト指向言語ではクラスなど) に属する値には, その型のメソッドを用いた操作が可能です.

同様に, “ある型クラスに属する型” に属する値には, その型クラスのメソッドを用いた操作を行うことが可能です.

インターフェース (あるいは抽象クラス ?) と型クラスの違いは以下の表のような感じです.

インターフェース型クラス
アドホック多相関数
デフォルト実装
多相定数×
高階型×
既存の型の拡張×
(JS での) 使いやすさ

型クラスは, そのための機能が含まれている言語でしか使えないものではなく, JavaScript のような言語でも定義できます.

インスタンスベースの特徴が明らかになってきました。

インスタンスベースで生成されたオブジェクトは、クラスに属してOK=オブジェクトを型で取り扱い可能と。

なお、「プロトタイプベース」においてその名が示す「プロトタイプの複製でオブジェクトを生成する」という特徴は、(クラスが必須のクラスベースでは、クラスを new できるのに対し)インスタンスベースでクラスがないときに使われるオブジェクト生成のバリエーションのひとつ…という程度の位置づけにすぎず、そうでなければならないという類のものではありません。

インスタンスベースとプロトタイプベースの包含関係について定義されていました。

プロトタイプベースは「インスタンスベースでクラスがないときに使われるオブジェクト生成のバリエーションのひとつ」という位置づけだそうです。

つまり、プロトタイプベースはインスタンスベースの真部分集合と定義されています。

  1. インスタンスベースで、クラスがあるときに使われるオブジェクトの生成=呼名は?
  2. インスタンスベースで、クラスがないときに使われるオブジェクトの生成=プロトタイプベース

の2種類に分類されています。

後者が「プロトタイプベース」なら、前者は区別するときに何と呼べばよいのでしょうか?=「非プロトタイプベースのインスタンスベース」を一言で示すときの名前は?

ここまでの説明では、前者と後者を区別するための名前が、まだ前者に与えられていないようです。

このオブジェクト生成にからめた「プロトタイプベース」関連の用語としては、「プロトタイプとクローン(コピー)」、「ペアレントとチャイルド」という用語やそれぞれの関係も混乱の元になりがちですね。

これらも、オリジナルとその浅いコピーの関係なら「プロトタイプとクローン」、委譲先としての情報を持つだけなら「ペアレントとチャイルド」と統一してはどうかと個人的には思うのですが、現状、ペアレント(移譲先の)スロットを「プロトタイプ」やそれに準ずる呼称とする言語が多い(関連して「プロトタイプ・チェーン」なんて言葉があるくらいですし…)ので、難しいですね。

もしこの提案を受け入れてもらえるなら、インスタンスベース的視点において、ネタ元のオブジェクトの呼び名は「Function.prototype をペアレントとするオブジェクト」あるいは「Function.prototype のチャイルド」というのがふさわしいということにできて一件落着なのですが、なかなかそういうわけにもいかないでしょう。

であれば、「Function.prototype を移譲先に持つオブジェクト」…かしらん(とはいえ、.prototype がうざいね汗)。

JavaScriptのオブジェクト指向を「プロトタイプベース」ではなく「インスタンスベース」と呼ぶ提案は、斬新だと思います。

「インスタンスベース」という用語について、

  1. オブジェクトの生成方法による分類
  2. オブジェクトの性質による分類
  3. 他のプロトタイプベース言語の違いを明示

これらの項目で分類表を作り、「プロトタイプベース」との差異や、包含関係を図表にしたら、分かりやすい説明方法が作れそうだと思いました。

本来のプロトタイプベースとは?

JavaScriptをプロトタイプベースのオブジェクト指向言語と言うべきではない – id:anatooのブログ

ウェブ上の記事を眺めていると、JavaScriptをプロトタイプベースのオブジェクト指向言語(以下OOPと書く)と説明している例がよく散見される。この書き方は間違ってはいないかもしれないが、もはや誤解を生むだけである。

JavaScriptはプロトタイプベースのOOPの中でも異端であり、本来のプロトタイプベースのOOPとはあまり似ていないからである。

JavaScriptでは、new演算子を使ってオブジェクトを生成したり、prototypeオブジェクトを使ってオブジェクトのメソッドやプロパティを定義したりするが、他のプロトタイプベースのOOPではnew演算子は無いし、prototypeオブジェクトも無い。

この記事では、本来のプロトタイプベースのOOPがどういったものであり、JavaScriptとはどう違うのかを説明する。

  • JavaScriptはプロトタイプベースの異端
  • 他のプロトタイプベースのOOPではnew演算子は無いし、prototypeオブジェクトも無い。

ここでは、プロトタイプベースのOOPの例として、ioという言語で説明する。

ioは純粋なプロトタイプベースのOOPだ。

また、ioには制御構文用の文法が無く全てが(if文ですらも)メソッドである。

ioは「7つの言語 7つの世界」という本で紹介されているプログラム言語です。

Io (プログラミング言語) – Wikipedia

Io は純粋なオブジェクト指向プログラミング言語であり、Smalltalk、Self、Lua、LISP、Act1、NewtonScriptの影響を受けている。

Self や NewtonScript のようなプロトタイプベースのオブジェクトモデルであり、オブジェクトとクラスを区別しない。

Smalltalk のようにあらゆるものをオブジェクトとして扱い、動的型付けを行う。

LISPのように文の概念がなく、制御フローは関数を使って実現される。

新たなオブジェクトはクローニングで生成される。

Io では新たな空のオブジェクトが作られたとき、その親との違いだけが新しいオブジェクトに格納される。

このような方式を差分継承と呼ぶ。

ioは、とても特徴的な言語仕様ですね?

重要なことはこのMyObjectはすでに利用できる一個のオブジェクトだということだ。

例えば、ここでcreateGreetingメソッドを呼び出せばそれはそのまま動作する。

JavaScriptではこうはいかない。

ioでは新しくオブジェクトを作るときには、クラスをインスタンス化してオブジェクトを生成する代わりに、すでにあるオブジェクトを複製することでオブジェクトを生成する。

さて、ioのやり方を見るとJavaScriptとはだいぶ違うことがわかる。

ioなどのプロトタイプベースのOOPではオブジェクトの定義や継承や生成などの処理を全てcloneを通じて行えるので非常にシンプルだ。

それに比べるとJavaScriptのprototypeオブジェクトを使うやり方は何かちぐはぐな印象を与えてくる。

GoFのデザインパターンの一つにオブジェクトの生成に関わるプロトタイプパターンというのがあるが、プロトタイプベースのOOPではこのデザインパターンを言語の設計レベルで全面的に採用することでnew演算子やクラスの存在を消してしまっている。

JavaScriptでは、プロトタイプ(ひな形)となるオブジェクトは関数オブジェクトのprototypeプロパティに代入したオブジェクトになるが、これは通常のオブジェクトとしてそのまま利用できるわけではないし、これはある意味クラスを表現するクラスオブジェクトのような形になっている。

ioではそういったオブジェクトは無くプロトタイプ(ひな形)となるのはそのオブジェクト自身である。

ioではオブジェクトの複製を通じてのみ新しいオブジェクトを生成できる。

こうやって書いてみると、JavaScriptが通常のプロトタイプベースのOOPとどれほどかけ離れているかがわかる。

JavaScriptはクラスを持たないためプロトタイプベースのOOPとして分類できるのかもしれないが、その仕組みを観察してみると、クラスベースとプロトタイプベースの合いの子のような妙な形になっている。

ioという具体的なプログラミング言語を挙げて考察しており、分かりやすい説明だと思いました。

ioとJavaScriptの比較項目

  1. オブジェクトの生成方法
  2. オブジェクトの性質(振る舞い)

「io」は、とてもスッキリした仕組み!

「io」のOOPを「純粋なプロトタイプベース」と呼ぶなら、JSのOOPの方式は別の名称で区別した方が良いかもしれませんね?

混乱を招かないなら、「オブジェクトベース」とか「インスタンスベース」を新名称として採用し、意味をシッカリと定義すれば良いでしょう。

他の言語との兼ね合いで、「オブジェクトベース」「インスタンスベース」という名称だと、別の混乱を招くとしたら、今までにない新しい名前を付けるべきでしょう。

→ 是非、JS界隈で検討してください。(大喜利大会)

決定打がない間は

  • 「JavaScript方式」
  • 「JavaScriptベース」

とか、そのまんまのネーミングでもいいかな?

=少なくとも、他の言語と衝突する可能性は100%ない!?

Mozillaへの提案

最近、「フェイクニュース」(偽のニュース)という言葉をよく聞きますが、人の話は鵜呑みにせず、自分で確かめることが大事ですね?

当たり前だと思っていることでも、別の角度から見たら、違う風景・姿が見えてきます。

「開発者やみんながそう言ってるから」という理由で、今までJavaScriptのOOPは「プロトタイプベース」と呼んできました。

しかし、世の中にはいろいろなプログラミング言語が存在しているので、混乱は避けるべきです。齟齬を生じさせないためにも、「プロトタイプベース」という用語の意味を再定義して、より厳密な説明に使えるように、概念を細分化/再構築した方が良いと思いました。

学校などの教育現場で、JavaScriptを教える場合があれば、名前と実体が正確に紐づいていないと、生徒が混乱してかわいそうですよね?

もしも、本記事をJavaScriptのガチ勢(ベテラン)さんが読まれましたら、「プロトタイプベース」という用語の用法について再検討/再定義して、分類表や図を作り、より分かりやすい説明をMozillaに提案していただけたらと思います。\(丸投げ)/

「Aは間違っている」→「AではなくBが正しい」=代替案のない批判は片手落ちです。

JavaScriptの開発者が間違えているなら、正しい答を教えてあげるのが親切ですね★

↓↓↓報告先はこちら

まとめ

  • 現状では、JavaScriptのオブジェクト指向は「プロトタイプベース」という名称で説明しておく。(理由:Mozilla自身がそう言ってるから。)
  • ただし、異論が出されたら「io」など他のプロトタイプベースの言語と比較するとJavaScriptの仕組みはちょっと違う、という説明もしておく。
  • 状況を整理して、図表などを作り、Mozillaに新名称を提案してみる。
  • JavaScriptのオブジェクト指向の方式について、Mozillaが新名称を採用し発表したら、その後は新名称を使えばOK。

投稿日:March 29th 2017

元記事:http://jsstudy.hatenablog.com/entry/2017/03/29/181613

– PR –
– PR –