ECMAScript
ここまでJavaScriptの基本文法について見ていきましたが、その文法を定めるECMAScriptという仕様自体がどのように変化していくのかを見ていきましょう。
ECMAScriptはEcma Internationalという団体によって標準化されている仕様です。 Ecma InternationalはECMAScript以外にもC#やDartなどの標準化作業をしています。 Ecma International中のTechnical Committee 39(TC39)という技術委員会が中心となって、ECMAScript仕様についてを議論しています。 この技術委員会はMicrosoft、Mozilla、Google、AppleといったブラウザベンダーやECMAScriptに関心のある企業などによって構成されます。
ECMAScriptのバージョンの歴史
ここで、簡単にECMAScriptのバージョンの歴史を振り返ってみましょう。
バージョン | リリース時期 |
---|---|
1 | 1997年6月 |
2 | 1998年6月 |
3 | 1999年12月 |
4 | 破棄1 |
5 | 2009年12月 |
5.1 | 2011年6月 |
2015 | 2015年6月 |
2016 | 2016年6月 |
2017 | 2017年6月 |
ES5.1からES2015がでるまで4年もの歳月がかかっているの対して、ES2015以降は毎年リリースされています。 毎年安定したリリースを行えるようになったのは、ES2015以降は仕様策定プロセスの変更が行われたためです。
Living StandardとなるECMAScript
現在、ECMAScriptの仕様書のドラフトはGitHub上のtc39/ecma262で管理されており日々更新されています。 そのため、本当の意味での最新のECMAScript仕様はhttps://tc39.github.io/ecma262/となります。 このように更新ごとにバージョン番号を付けずに、常に最新版を公開する仕様のことをLiving Standardと呼びます。
ECMAScriptはLiving Standardですが、これに加えてECMAScript 2017のようにバージョン番号をつけたものも公開されています。 このバージョン付きECMAScriptは、毎年決まった時期のドラフトを元にしたスナップショットのようなものです。
ブラウザなどに実際にJavaScriptとして実装される際には、Living StandardのECMAScriptを参照しています。 これは、ブラウザ自体も日々更新されるものであり、決まった時期にしかリリースされないバージョン付きよりもLiving Standardの方が適当であるためです。
仕様策定のプロセス
ES2015以前はすべての仕様の合意が取れるまで延々と議論を続けすべてが決まってからリリースされていました。 そのため、ES2015がリリースされるまでには6年もの歳月がかかり言語の進化が停滞していました。 この問題を解消するために、TC39は毎年リリースするためにECMAScriptの策定プロセスを変更しました。
この策定プロセスはES2015がリリース後に適応され、このプロセスで初めてリリースされたのがES2016となります。 ES2016以降では、次のような仕様策定のプロセスで議論を進めて仕様が決定されています。2
仕様に追加する機能(API、構文など)をそれぞれ個別のプロポーザル(提案書)として進めていきます。
現在策定中のプロポーザルはGitHub上のtc39/proposalsに一覧が公開されています。
それぞれのプロポーザルは責任者であるチャンピオンとステージ(Stage)と呼ばれる0
から4
の5段階の状態を持ちます。
ステージ | ステージの概要 |
---|---|
0 | アイデアの段階 |
1 | 機能提案の段階 |
2 | 機能の仕様書ドラフトを作成した段階 |
3 | 仕様としては完成しており、ブラウザの実装やフィードバックを求める段階 |
4 | 仕様策定が完了し、2つ以上の実装が存在している。 正式にECMAScriptにマージできる段階 |
2ヶ月に一度行われるTC39のミーティングにおいて、プロポーザルごとにステージを進めるかどうかを議論します。
このミーティングの議事録もGitHub上のtc39/tc39-notesにて公開されています。
ステージ4となったプロポーザルはドラフト版であるtc39/ecma262へマージされます。
そして毎年の決まった時期にドラフト版を元にしてECMAScript 20XX
としてリリースします。
この仕様策定プロセスの変更は、ECMAScriptに含まれる機能の形にも影響しています。
たとえば、class
構文の策定は最大限に最小のクラス(maximally minimal classes)と呼ばれる形で提案されています。
これによりES2015でclass
構文が導入されましたが、クラスとして合意が取れる最低限の機能だけの状態で入りました。
その他のクラスの機能は別のプロポーザルとして提案され、ES2015以降に持ち越された形で議論が進められています。
このような合意が取れる最低限の形でプロポーザルを進めていくのには、ES4の苦い失敗が背景にあります。 ES4ではECMAScriptに多くの変更を入れることを試みましたが、TC39内でも意見が分かれ最終的に合意できませんでした。 これによりES4の策定に割いた数年分のリソースが無駄となってしまったという経緯があります。3
ES2016以降の策定プロセスでも、すべてのプロポーザルが仕様に入るわけではありません。4 別の代替プロポーザルが出た場合や後方互換性と保てない場合などにプロポーザルの策定を中断する場合があります。 しかし、この場合でもプロポーザルという単位であるため策定作業の無駄は最小限で済みます。 このようにモジュール化されたプロポーザルは入れ替えがし易いという性質もあります。
プロポーザルの機能を試す
ECMAScriptの策定プロセスのステージ4に「2つ以上の実装が存在している」という項目があります。 そのためブラウザのJavaScriptエンジンには、策定中のプロポーザルが実装されている場合があります。 多くの場合は試験的なフラグ付きで実装されておりフラグを有効化することで、試すことができるようになっています。
またTranspilerやPolyfillといった手段で、プロポーザルの機能をエミュレートできる場合があります。
Transpilerとは、新しい構文を既存の機能で再現できるようにソースコードを変換するツールのことです。
たとえば、ES2015でclass
構文が導入されましたが、ES5ではclass
は予約語であるため構文エラーとなり実行できません。
Transpilerでは、class
構文を含むソースコードをfunction
キーワードを使い擬似的に再現するコードへ変換します。
TranspilerとしてはBabelやTypeScriptなどが有名です。
Polyfillとは、新しい関数やメソッドなどの仕様を満たすような実装を提供するライブラリのことです。
たとえば、ES2016ではArray#includes
というメソッドが追加されました。
構文とは異なりArray#includes
のようなメソッドはビルトインオブジェクトを書き換えることで実装できます。
Polyfillを提供するものとしてはcore-jsやpolyfill.ioなどが有名です。
注意点としてはTranspilerやPolyfillは、あくまで既存の機能を用いて新しい機能の再現を試みているだけに過ぎません。 そのため、既存の機能で再現ができないプロポーザル(機能)はTranspilerやPolyfillでは再現できません。 また、完全な再現はできていないことがあるためTranspilerやPolyfillを新しい機能を学ぶために使うべきではありません。
仕様や策定プロセスを知る意味
こうしたECMAScriptという仕様や策定プロセスを知る意味は何があるのでしょうか? 主に次のような理由で知る意味があると考えています。
- 言語を学ぶため
- 言語が進化しているため
- 情報の正しい状態を調べるため
言語を学ぶため
もっとも単純な理由はJavaScriptという言語そのものを学ぶためです。 言語の詳細を知りたい場合にはECMAScriptという仕様を参照できます。
しかしながら、JavaScriptの言語機能に関してはMDN Web Docsという優れたリファレンスサイトなどがあります。 そのため、使い方を覚えたいなどの範囲ではECMAScriptの仕様そのものを参照する機会は少ないでしょう。
言語が進化しているため
ECMAScriptはLiving Standardであり、日々更新されています。 これは、言語仕様に新しい機能や修正などが常に行われていることを表しています。
ECMAScriptは後方互換性を尊重するため、今学んでいることが無駄になるわけではありません。 しかしながら言語自体も進化していることは意識しておくとよいでしょう。
ECMAScriptのプロポーザル(機能)は問題を解決するために提案されます。 そのプロポーザルがECMAScriptにマージされ利用できる場合、その機能が何を解決するために導入されたのか知ることは大切です。 その際には、ECMAScriptの策定プロセスを知っておくことが調べることに役立ちます。
この仕様はなぜこうなったのかということを知りたいと思ったときに、その機能がどのような経緯で入ったのかを調べる手段をもつことは大切です。 特にES2015以降は策定プロセスもGitHubを利用したオープンなものとなり、過去の記録なども探しやすくなっています。
情報の正しい状態を調べるため
JavaScriptは幅広く使われている言語であるため、世の中には膨大な情報があります。 そして、検索して見つかる情報には正しいものや間違ったものが混在しています。
その中においてECMAScriptの仕様やその策定中のプロポーザルに関する情報は状態が明確です。 基本的にECMAScriptの仕様に入ったものは、後方互換性を維持するために破壊的変更は殆ど行なえません。 プロポーザルはステージという明示された状態があり、ステージ4未満の場合はまだ安定していないことが分かります。
そのため、問題を見つけた際に該当する仕様やプロポーザルを確認してみることは重要です。
これはECMAScriptにかぎらず、ウェブやブラウザに関する情報に関しては同じことがいえます。 ブラウザに関してはHTML、DOM API、CSSなどのオープンな仕様とそれぞれの策定プロセスが存在しています。
まとめ
JavaScriptと一言にいってもECMAScript、ブラウザ、Node.js、WebAssembly、WebGL、WebRTCなど幅広い分野があります。 そのためすべてのことを知っている必要はありませんし、知っている人もおそらくいないでしょう。 このような状況下においては知識そのものよりも、それについて知りたいと思ったときに調べる方法を持っていることが大切です。
なにごとも突然全く新しい概念が増えるわけではなく、ものごとには過程が存在します。 ECMAScriptにおいては策定プロセスという形でどのような段階であるかが公開されています。 つまり、仕様にいきなり新しい機能が増えるのではなくプロポーザルという段階を踏んでいます。
日々変化しているソフトウェアにおいては、自身に適切な調べ方をもつことが大切です。
1. ECMAScript 4は複雑で大きな変更が含まれており、合意を得ることができずに策定仕様が破棄されました。 ↩
2. この策定プロセスはhttps://tc39.github.io/process-document/に詳細が書かれています。 ↩
3. ES2015の仕様編集者であるAllen Wirfs-Brock氏の書いたProgramming Language Standardizationに詳細が書かれています。 ↩
4. Inactive Proposalsに策定を中止したプロポーザルの一覧が公開されています。 ↩