CoffeeScript 2という新たなる希望

## CoffeeScriptは滅びぬ！何度でも蘇るさ！

CoffeeScriptが[いかに駄目か](http://qiita.com/raccy/items/fae9fc5923d78112d935)を理解している皆さんならご存じの通り、これまでの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](http://coffeescript.org/)だ。バージョンが上がっただけでないかと言うかも知れないが、最初に述べた重大な欠点が修正されている。そう、「**CoffeeScript 2はECMASCript2015以降(ES2015+)のaltJSである**」と言えるようになっている事だ。CoffeeScript 2はコンパイル後の出力でES2015+のコードを吐き出す。最新のNode.jsなどES2015+に対応したJavaScriptエンジンであればそのまま実行することが可能だ。[^1]

[^1]: Node.js 7.6以上で動作するES2015+をターゲットにしている。ただし、Node.jsが対応していない`import`/`export`のモジュール機能とJSXについてはそのまま出力されるためBabelと組み合わせた変換が必要になる。

## 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]
* 分割代入

[^2]: 提案中で正式未採用のobjectリテラルに対しても使用できるが、ES2015+で正式採用まではBabelと同じpolyfillになる。

#### ファットアロー(`=>`)なジェネレーター関数は作成できない

ジェネレーター関数は1.xの時からある機能であり、ファットアローに対しても使用することができた。しかし、ファットアローのジェネレーター関数はES2015+に存在しない機能であるため、ファットアローをそのまま出力するCoffeeScript 2では使用できなくなった。[^3]

[^3]: ECAMScriptの仕様書提案にGenerator arrow functions (`=>*`)があるので、採用されればいずれ復活するかも知れない。

#### `super`のみが使えない

1.xでは`super`のみで親クラスのメソッドを引数そのままで呼び出せたが、2では通常の関数と同じく`super()`と呼び出す必要がある。また、ES2015+と同じく子クラスのconstructorでは最初に`super()`の呼び出しは必須になった。

## CoffeeScriptは本当にオワコンなのか？

ECMAScript2015のリリース、静的型付けのためのTypeScriptの流行、トレンドの推移としてはCoffeeScriptは落ち目であり、「CoffeeScriptはオワコン」とか言っている[Qiitaの記事](http://qiita.com/raccy/items/fae9fc5923d78112d935#%E4%BF%BA%E3%81%9F%E3%81%A1%E3%81%AE%E6%88%A6%E3%81%84%E3%81%AF%E3%81%93%E3%82%8C%E3%81%8B%E3%82%89%E3%81%A0)も見られる。あえて言おう、(リンク先の記事は)カスであると！また、新たな時代が始まる、それがCoffeeScript 2だ。本当に良いものはバージョン2になって初めてその力を発揮する。Java 2[^4]、Ruby 2[^5]、TypeScript 2、Solaris 2[^6]、HTTP/2等々、2から本気を出しているものは数多い。そう、本番はこれからなのだ。

[^4]: Javaは1.2からJava 2になり、最新のJavaもJava 2を(2はいつの間にか消したけど)そのまま継承している。

[^5]: Rubyが大きく変わったのは1.9からだろとかそういうことは言わない。

[^6]: Solarisは2.0、2.1、とずっと2.xが続いたが、いつの間にか2.の部分が無くなった。でも2のままだ。

時代は巡る。やれ、静的型付けだ、null安全だ、と言っている輩も、動的型付けこそ至高、ダック・タイピングこそ正義、という真理[^7]をそのうち理解することだろう。そしてTypeScriptの時代は終わり、再びCoffeeScript 2の時代がやってくる、たぶん。

[^7]: 君が持つ「真理」と私が持つ「真理」が同一であるとは限らないがな。