ES2015再入門


#ES2015とは？

将来的にはブラウザに対応される予定の **「今までのJS(ES5)に様々な機能が追加された新仕様」** のこと。
ES6とも言ったりします。

現在は一部のみ（Chromeは対応）で機能が実装されていたり、されていなかったり。
Babelのドキュメントに機能の一覧がまとめられています。
https://babeljs.io/docs/learn-es2015/


##BABELって？

**ES2015仕様のJavascriptをES5仕様に整形するツール** です。

ES2015に対応していないブラウザのために、
「ES2015の記法で書いたコード」 => 「ES5」
としてくれる。

##対応していないんなら必要ないのでは？

**将来的にはブラウザに実装されていく** ものなので、今から使って慣れておいた方がよさそうです。

#ES2015で書いてみよう

ES2015についてのチュートリアルがあったのでやってみました。
http://ccoenraets.github.io/es6-tutorial/setup-babel/

ES2015全ての内容をさらえているわけではないですが、
「勉強しなきゃいけない...とはわかっているんだけど...」と重い腰があがらない者としてはとっかかりとしてあるととっても助かります。

# 変数がブロックスコープでのみ有効になる `let` が追加

## ブロックスコープが効かないjs

```js
var calculateMonthlyPayment = function (principal, years, rate) {
    if (rate) {
        var monthlyRate = rate / 100 / 12;
    }
    var monthlyPayment = principal * monthlyRate / (1 - (Math.pow(1 / (1 + monthlyRate), years * 12)));
    return monthlyPayment;
};
```

[phpなどと違って、jsにはブロックレベルでのスコープが無い](http://qiita.com/matsuby/items/1010ae38ee6258fd8020#%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%97
)、ので `if` の中で定義した `monthlyRate` が外でも使える。
phpとかと同じ感覚で書いてしまうと、意図しないところで変数が上書きされたりしそうで危険。

##letを使う

ES2015で追加された `let` を使うと、ブロックスコープを有効に出来る様になる。

```js
let calculateMonthlyPayment = function (principal, years, rate) {
    let monthlyRate = 0; //letはブロックスコープで有効なので、外で定義が必要になった
    if (rate) {
        monthlyRate = rate / 100 / 12;
    }
    let monthlyPayment = principal * monthlyRate / (1 - (Math.pow(1 / (1 + monthlyRate), years * 12)));
    return monthlyPayment;
};
```

# オブジェクトの書き方がシンプルに

## キーとバリューが同じなら書かなくても済むようになった

```js
return {principal, years, rate, monthlyPayment, monthlyRate};
```

と書くだけで、

```js
return { principal: principal, 
         years: years, 
         rate: rate, 
         monthlyPayment: monthlyPayment, 
         monthlyRate: monthlyRate };
```

と同じ意味になる。

## 同じものを使うやつ

```js
let {monthlyPayment, monthlyRate} = calculateMonthlyPayment(principal, years, rate);
```

とすれば

```js
var mortgage = calculateMonthlyPayment(principal, years, rate);
var monthlyPayment = mortgage.monthlyPayment;
var monthlyRate = mortgage.monthlyRate;
```

となる。
わかりやすくかくと

```js
let {Tom, John} = profile(years, birthday);
```

は

```js
var mortgage = profile(years, birthday);
var Tom = mortgage.Tom;
var John = mortgage.John;
```

みたいな？

# `function(){}` が `()=>{}` で済むようになった

スペルミスが減るというメリット。
あとは `this` が使えなくなるらしいです。

```js
let calculateAmortization = (principal, years, rate) => {
    let {monthlyRate, monthlyPayment} = calculateMonthlyPayment(principal, years, rate);
    let balance = principal;
    let amortization = [];
    for (let y=0; y<years; y++) {
        let interestY = 0;  //Interest payment for year y
        let principalY = 0; //Principal payment for year y
        for (let m=0; m<12; m++) {
            let interestM = balance * monthlyRate;       //Interest payment for month m
            let principalM = monthlyPayment - interestM; //Principal payment for month m
            interestY = interestY + interestM;
            principalY = principalY + principalM;
            balance = balance - principalM;
        }
        amortization.push({principalY, interestY, balance});
    }
    return {monthlyPayment, monthlyRate, amortization};
};
```

#Module化の記法がシンプルに

##今までは `require` をする必要があった

###読み込む方

```js:common.js
var sub1 = require(“./modules/sub1.js”);
var sub2 = require(“./modules/sub2.js”);

sub1.hello( );
sub1.goodmorning( );

sub2( );
```

###読み込まれる方

```js:sub.js
module.exports.hello = function( ){
	console.log(“hello!”);
};

module.exports.goodmorning = function(){
	console.log(“goodmorning”);
};
```

##新記法

###読み込む方

「**という名前で(as)***ディレクトリから(from)インポートする」という書き方になった。

```js:common.js
import * as mortgage from './mortgage';
import * as hoge from './hoge';
```

###読み込まれる方

`export` を関数の前につけるだけ。

```js:hoge.js
export let hoge = () => {
    console.log("piyopiyo")
}
```

#Classが使える

作ったクラスは `export default` でエクスポートする。

```js
export default class Mortgage {

    constructor(principal, years, rate) {
        this.principal = principal;
        this.years = years;
        this.rate = rate;
    }

    get monthlyPayment() {
        let monthlyRate = this.rate / 100 / 12;
        return this.principal * monthlyRate / (1 - (Math.pow(1/(1 + monthlyRate),
                this.years * 12)));
    }

    get amortization() {
        let monthlyPayment = this.monthlyPayment;
        let monthlyRate = this.rate / 100 / 12;
        let balance = this.principal;
        let amortization = [];
        for (let y=0; y<this.years; y++) {
            let interestY = 0;
            let principalY = 0;
            for (let m=0; m<12; m++) {
                let interestM = balance * monthlyRate;
                let principalM = monthlyPayment - interestM;
                interestY = interestY + interestM;
                principalY = principalY + principalM;
                balance = balance - principalM;
            }
            amortization.push({principalY, interestY, balance});
        }
        return amortization;
    }

}
```

インポートするときはModuleのときと同じように。

```js
import Mortgage from './mortgage2';
```

#Promiseを使う

`Promise` をnewして、

```js
let rates = [
    {
        "name": "30 years fixed",
        "rate": "13",
        "years": "30"
    },
    {
        "name": "20 years fixed",
        "rate": "2.8",
        "years": "20"
    }
];

export let findAll = () => new Promise((resolve, reject) => {
    if (rates) {
        resolve(rates);
    } else {
        reject("No rates");
}
});
```

こんな感じで使う。

```js
import * as service from './rate-service-mock';

service.findAll()
    .then(rates => {
    let html = '';
rates.forEach(rate => html += `<tr><td>${rate.name}</td><td>${rate.years}</td><td>${rate.rate}%</td></tr>`);
document.getElementById("rates").innerHTML = html;
})
.catch(e => console.log(e));
```

エラーのときの処理は `catch` に書いてる。

## Promiseについてのいい記事
[Promiseと仲良くなって気持ち良く非同期処理を書こう - Qiita](http://qiita.com/progre/items/03626b7f4655007d8cb2)


#出てきてないけど勉強すべき項目

- Destructuring
- Default + Rest + Spread
- Const
- Iterators + For..Of
- Map + Set + WeakMap + WeakSet
- Proxies

この辺はまた次の機会にでも。

#感想

- 記法がシンプルになった感じ
	- とはいえ、正直なところ元の記法にあまり慣れていなかったのでいまいちピンとこない
	- 逆に言えば、この記法に慣れてしまえばいいのでは？
- Promiseのところとかは「非同期処理」自体についてもう少し勉強したほうがいいかも