さてjavascriptを書いている皆さん、 es2015への対応準備はいかがでしょうか?
個人的には **2016年こそがes2015元年になるのではないか(ややこしい)**という見立てでおります。
無論、ブラウザ自体の対応はまだまだなのですが、
ブラウザ互換のjavascriptに変換してくれるBabelも(あるていど)安定し、
browserify等々との連携も便利になってきたこの頃、意識しなくても使えるようになってきたのでは、というこのごろです。
「そうは言っても、本来ブラウザで動かないし、javascriptに新しい機能が付くわけでもないし、使うメリットなんてそんなにないのでは?」
と思う方もいるかもしれません。自分もしばらくそう思ってました。
しかし明確なメリットが一つあります。
javascriptならではの読みづらい部分を、圧倒的に読みやすく書き直せることです。
そんなわけでこの記事では、javascriptの嫌なところを読みやすく書きなおすという観点のみで、es2015を紹介してみます。
class
こちらに何の変哲もないjavascriptがあります。押したらalertが出るだけのボタンを作るやつですね。
var HelloButton = function (name, btn) {
this.name = name;
this.btn = btn;
this.setListener();
};
HelloButton.prototype.hello = function () {
alert("hello, my name is " + this.name + " !");
};
HelloButton.prototype.setListener = function () {
var that = this;
this.btn.addEventListener('click', function (e) {
that.hello();
});
};
javascriptを書いている人なら、普通に「あ、クラスだ」と思うかもしれません。
しかしこれ厳密に言えば、これは「クラスっぽいもの」であってクラスではありませんし、別の書き方で「クラスっぽいもの」を実現している人もいます。(privateなプロパティはvar宣言にするなど)
また、これが「クラスっぽいな」と思うのは、prototypeの拡張が後からごろごろ書いてあるからであって、
例えば最初の5行くらいを見ただけでは、このHelloButton
という関数を、関数として使うのかクラスとして使うのかは判断しきれません。
それがes2015を使えばこのとおり、どう見たってクラスだね!というようなコードで書けます。
class HelloButton {
constructor (name, btn) {
this.name = name;
this.btn = btn;
this.setListener();
}
hello () {
alert("hello, my name is " + this.name + " !");
}
setListener () {
var that = this;
this.btn.addEventListener('click', function (e) {
that.hello();
});
}
}
coffeescript等を書いている人にとっては、とっつきやすい記法ではないでしょうか。extends等も同じような感じでできます。
ちなみにこちら、新しいリテラル(書き方)が提供されたというだけで、内部実装は前者と後者ほぼ変わらないということに注意です。
新しくクラスの概念ができたというよりは、みんながよく使う実装に正式な書き方ができた、という流れなのです。
arrow function
さて上記の例の中には他にも、javascriptを書く時に気持ち悪いと思うポイントが含まれています。例えばこちら、setListener
の中身を取り出したものです。
var that = this;
this.btn.addEventListener('click', function (e) {
that.hello();
});
そのthat
はなんなんだと。
念のため解説しておくと、こちらをthat
なしで、そのままthis.hello()
と書くとエラーになります。
var that = this
の行の時点では、this
には自分自身・つまりHelloButton
のインスタンスが入っていますが、
addEventListener
に渡されたfunctionの中・that.hello()
の部分では、thisにはボタンの要素が入っています。
当然ボタンの要素はhelloメソッドを持っていないので、this.hello()
で呼び出すとエラーになります。それを避けるため、HelloButton
のインスタンスがとれるタイミングで一度変数に代入しておき、後から参照する、という書き方がよく用いられているわけです。
この厄介な都合を避ける書き方も、es2015では提供されています。「arrow function」というやつです。
this.btn.addEventListener('click', (e) => {
this.hello();
});
function (e) { ... }
ではなく、(e) => { ... }
という書き方にすることで、関数内部のthis
は、その外側のthis
を引き継ぐようになります。これで分かりやすいですね。
クラスを使った実装をする場面では少なくとも、このようにthis
の内容がころころ変わらないように意識したほうが、読みやすいコードになると思います。
template
また、この辺も書く時にイライラする部分です。
alert("hello, my name is " + this.name + " !");
変数が入り混じった文字列を作りたい時の書き方ですね。これくらいなら変数が一つなのでなんとかなりますが、3つや4つと増えてきた時には見づらくてかなわないですね。
そこでes2015の「template」記法が使えます。
alert(`hello, my name is ${this.name} !`);
1, クオートを`に置き換える
2, 変数を入れ込みたい部分を${ ... }
で囲む
とすることで、文字列全体を一組の``でまとめつつ、展開が必要なところだけ整理して書くことができます。ちなみに改行もOKです。
つまり
すべてを反映すると、最初のコードはこんな感じになります。
class HelloButton {
constructor (name, btn) {
this.name = name;
this.btn = btn;
this.setListener();
}
hello () {
alert(`hello, my name is ${this.name} !`);
}
setListener () {
this.btn.addEventListener('click', (e) => {
this.hello();
});
}
}
色んな面で見やすくなったのではないでしょうか。
これなら、例えばRubyしか書いたことがない人でも、なんとなく読み取ってくれそうな気配さえします。
また結果的に、function
文を使う場面がなくなっていることにも注目です。
環境構築
さて、みなさんes2015が書きたくなってきましたよね。
現状そのために必要な環境構築は、以下の様な感じです。
nodeをご利用のみなさま
→今すぐ書き換えちゃいましょう。
- 一部
use strict
が必須です。 - es2015をサポートし始めたのが4.0.0あたりからなので、package.jsonでenginesを4.0.0以上にするのをおすすめしてます。
フロントエンジニアのみなさま
→babel環境をととのえましょう。
-
色んな開発環境で使えるようになってますが、import/exportまで含めてちゃんと使えるという意味では、webpack+babelかbrowserify+babelifyがおすすめです。
-
個人的にはこんなかんじで使ってます。
ではではみなさま、今年も読みやすいjavascriptを書いていきましょうー!