Edited at

可読性アップのためのes2015入門

More than 3 years have passed since last update.

さて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環境をととのえましょう。

ではではみなさま、今年も読みやすいjavascriptを書いていきましょうー!