CoffeeScriptは滅びぬ!何度でも蘇るさ!
CoffeeScriptがいかに駄目かを理解している皆さんならご存じの通り、これまでのCoffeeScriptには重大な欠点があった。それは「CoffeeScriptはECMAScript5(ES5)のaltJSである」と言うことだ。ES5以前のJavaScriptが駄目すぎるため、そこがCoffeeScriptの限界になってしまっていた。駄目な奴は何をやっても駄目なのだ。
ECMAScript2015以降(ES2015+)において、JavaScriptは目覚ましい発展を遂げた。ジェネレーター、テンプレートリテラル、class構文、モジュールベース、async/await等多くの機能が追加された。いくつかの機能は既にCoffeeScriptに存在していたものであったが、ジェネレーターのような全く無い物は新たに追加する必要があった。しかし、追加されたCoffeeScriptのジェネレーターを見ればわかるとおり、ジェネレーターはジェネレーターとして出力するしか無く、ジェネレーターに対応した最新のブラウザでしか動作しないコードになってしまった。そのためかどうかわからないが、ES5以前には全く存在しないimport/exportやasync/awiat等の追加は難しくなっていたようだ。
しかし、それで滅びるようなCoffeeScriptでは無い。altJSとしてのターゲットがES5であることが問題であれば、ES2015+に変更すれば良いのだ。そして出てきたのがCoffeeScript 2だ。バージョンが上がっただけでないかと言うかも知れないが、最初に述べた重大な欠点が修正されている。そう、「CoffeeScript 2はECMASCript2015以降(ES2015+)のaltJSである」と言えるようになっている事だ。CoffeeScript 2はコンパイル後の出力でES2015+のコードを吐き出す。最新のNode.jsなどES2015+に対応したJavaScriptエンジンであればそのまま実行することが可能だ。1
CoffeeScript 2の使い方
使い方はCoffeeScriptと同じだ。既に2系が正式リリースされているため、インストールはcoffeescript
と指定するだけでよい。
npm install -g coffeescript
coffee -c example.coffee
example.coffeeはexample.jsとなり、Node.jsや最新のブラウザでそのまま実行できるだろう。もし、レガシーなブラウザや、対応環境が少ないimport
/export
文、JSXの使用を想定しているのであれば、Babelと組み合わせて使うこともできる。
npm install babel-core babel-preset-env babel-preset-react --save-dev
echo '{ "presets": ["env", "react"] }' > .babelrc
coffee -c -t example.coffee
Babelのコマンドを別途叩く必要は無い。CoffeeScriptがBabelでのトランスパイルも行ってくれる。
CoffeeScript 2の新機能と1.xからの変更点
2からの新機能と1.xからの変更点を見ていきたいと思う。
新機能
非同期関数(async
/await
)
関数内でawait
を使用していれば、非同期関数とみなす。1.xからあったyield
があればジェネレーター関数と見なすのと同じような動作になる。
タグ付けされたテンプレートリテラル
タグ付けされたテンプレートリテラルを使用できる。
モジュール(import
/export
)
モジュールとして使用するためにimport
/export
の構文が用意される。import
/export
はそのまま出力されるため、モジュールに対応していない環境では、Babelでの変換が必要になる。
JSX
JSX表記に対応している。ただし、JSX表記はJSX表記としてそのまま出力されるため、Babelでの変換が必要になる。
型アノテーション
型アノテーションを記載できる。変換後はFlowに対応した型アノテーションの記述になる。
1.xからの変更点
ES2015+にあるものはES2015+のネイティブとして出力
ES2015+でネイティブ表現可能なものはそのまま出力される。そのため、ES5にコンパイルしていた1.xとは細部の動作が一部異なる場合がある(【※】が付いているもの)。
- 関数引数と分割代入のデフォルト値 【※】
- ファットアロー関数(
=>
) 【※】 - クラス構文 【※】
- 展開(
#{...}
)がある文字列リテラル(テンプレートリテラルとして変換) - スプレッド演算子(
...
)2 - 分割代入
ファットアロー(=>
)なジェネレーター関数は作成できない
ジェネレーター関数は1.xの時からある機能であり、ファットアローに対しても使用することができた。しかし、ファットアローのジェネレーター関数はES2015+に存在しない機能であるため、ファットアローをそのまま出力するCoffeeScript 2では使用できなくなった。3
super
のみが使えない
1.xではsuper
のみで親クラスのメソッドを引数そのままで呼び出せたが、2では通常の関数と同じくsuper()
と呼び出す必要がある。また、ES2015+と同じく子クラスのconstructorでは最初にsuper()
の呼び出しは必須になった。
CoffeeScriptは本当にオワコンなのか?
ECMAScript2015のリリース、静的型付けのためのTypeScriptの流行、トレンドの推移としてはCoffeeScriptは落ち目であり、「CoffeeScriptはオワコン」とか言っているQiitaの記事も見られる。あえて言おう、(リンク先の記事は)カスであると!また、新たな時代が始まる、それがCoffeeScript 2だ。本当に良いものはバージョン2になって初めてその力を発揮する。Java 24、Ruby 25、TypeScript 2、Solaris 26、HTTP/2等々、2から本気を出しているものは数多い。そう、本番はこれからなのだ。
時代は巡る。やれ、静的型付けだ、null安全だ、と言っている輩も、動的型付けこそ至高、ダック・タイピングこそ正義、という真理7をそのうち理解することだろう。そしてTypeScriptの時代は終わり、再びCoffeeScript 2の時代がやってくる、たぶん。
-
Node.js 7.6以上で動作するES2015+をターゲットにしている。ただし、Node.jsが対応していない
import
/export
のモジュール機能とJSXについてはそのまま出力されるためBabelと組み合わせた変換が必要になる。 ↩ -
提案中で正式未採用のobjectリテラルに対しても使用できるが、ES2015+で正式採用まではBabelと同じpolyfillになる。 ↩
-
ECAMScriptの仕様書提案にGenerator arrow functions (
=>*
)があるので、採用されればいずれ復活するかも知れない。 ↩ -
Javaは1.2からJava 2になり、最新のJavaもJava 2を(2はいつの間にか消したけど)そのまま継承している。 ↩
-
Rubyが大きく変わったのは1.9からだろとかそういうことは言わない。 ↩
-
Solarisは2.0、2.1、とずっと2.xが続いたが、いつの間にか2.の部分が無くなった。でも2のままだ。 ↩
-
君が持つ「真理」と私が持つ「真理」が同一であるとは限らないがな。 ↩