ES2015 (ES6)についてのまとめ


##ECMAScriptとは
* ECMAScriptはJavaScriptの中核仕様を抜き出して標準化したもの
* 開発当初のJavascriptは、ブラウザによる独自の拡張が多く、互換性が低かったため、Ecma Internationalが中心となりECMAScriptが開発された

## ES2015 (ES6)とは
先日策定された、ECMASCriptの6th Editionのことであり、当初はES6と呼ばれているが、正式名称をECMASCript2015(ES2015と呼ばれる)とし、今後は年単位のリリースを予定しているとのこと
[公式サイト]http://www.ecma-international.org/ecma-262/6.0/index.html

## ES2015で可能となる新たなシンタックス

* `let`・`const`キーワードによる変数宣言
* `class`構文
* 関数の引数のデフォルトパラメータ（Default Parameters）
* アロー関数（Arrow Functions）
* 分割代入（Destructing Assignment）
* 配列展開（Array Spread）
* 関数の可変長引数（Rest Parameters）
* 関数のデフォルト引数
* テンプレート文字列（Template Strings）
* importとexportによるモジュール構文（Module）

### let constによる変数宣言
ES5までは関数スコープのみしか存在しなかったため、`var`による変数宣言に対して、スコープを利用するためには、無名関数を用いてスコープの作成をしていたが、
ES2015ではブラケット`{}`によるブロックスコープが可能となり、ブラケット内で`let`や`const`により定義された変数はそのブラケットのスコープ内のみで生きることができる。
`const`は定数を宣言したい時に用いられ、`const`で宣言された変数は、宣言時を除いて値の代入が不可能である。再代入を行おうとすると、例外が発生し、プログラムがストップするため、プログラムレベルで値の不変性が保証される。

```javascript
let foo = [1, 2, 3];
{
  let foo = [4, 5, 6];
  console.log(foo);
  // => 4, 5, 6
}
console.log(foo);
// => 1, 2, 3
```

```javascript
{
  const PI = 3.14;
  const circleArea = function (radius) {
    return radius * radius * PI;
  };
  console.log(circleArea(3));
  // => 28.26
  // ここでPI = 3.1415;のような再代入を行おうとすると、例外が発生する
}
console.log(PI);
// => undefined
```

### クラス構文
ES5までではprototype(あるオブジェクトの元になるオブジェクトという概念。RubyやJavaなどのクラスベースオブジェクト指向に対し、javascriptはプロトタイプベースオブジェクト指向と呼ばれる。)を利用することで、クラスのようなものを作成してきた。

```javascript
function Human(name) {
  this.name = name;
}
 
Human.prototype.hello = function () {
  console.log('My name is ' + this.name);
};
```

Humanオブジェクトはhelloオブジェクトをprototypeとしてできており、Humanオブジェクトはhelloオブジェクトに対する暗黙の参照をもっているため、helloというプロパティでhelloオブジェクトを呼び出すことができる

```javascript
obj = new Human('Izmeal')
obj.hello
//=> 'My name is Izmeal' 
```

これを、class構文を用いると、

```javascript
class Human {
  constructor(name) {
    this.name = name;
  }
  hello() {
    console.log('My name is ' + this.name);
  }
}
```

```javascript
obj = new Human('Koyabu')
obj.hello
//=> 'My name is Koyabu'
```

class構文についてもう少しみてみる。
### constructorメソッド
constructorメソッドは、クラスがnewされた時に実行されるメソッドであり、クラス内で共通して使われるプロパティの初期値の定義などを行う。1つのクラスに1つしか定義できない。先ほどの例ではnameの初期値を代入している。(Rubyでいうinitializeメソッド)

### prototypeメソッド
先ほどのHumanクラスのhelloのように、クラスのインスタンスから呼び出せるメソッドをprototypeメソッドという。(Rubyでいうインスタンスメソッド)

### staticメソッド

インスタンスを生成する必要なく`クラス名.メソッド名`の形で呼び出せるメソッド。(Rubyでいうクラスメソッド)

```javascript
class Human {
  constructor(name) {
    this.name = name;
  }
  hello() {
    console.log('My name is ' + this.name);
  }
  static num_of_hands() {
    console.log(2)
  }
}

Human.num_of_hands()
//=> 2
```

### クラスの継承
 extends キーワードをクラス宣言、もしくはクラス式内に記述することで、他のクラスの子クラスを定義できる。

```javascript
class Animal { 
  constructor(name) {
    this.name = name;
  }
  
  speak() {
    console.log(this.name + ' makes a noise.');
  }
}

class Dog extends Animal {
  speak() {
    console.log(this.name + ' barks.');
  }
}
```

子クラス内で、親クラスのconstructorは`super()`で呼び出せ、親クラスのメソッドは、`super.メソッド名()`で呼び出せる。

## アロー関数による関数宣言

従来の`funciton`を使った関数宣言に加えて、`=>`を用いた関数宣言が可能
アロー関数による関数宣言の特徴としては、
* 常に匿名関数
* 引数が一つの場合は()が省略可能
* bodyが単一式の場合は、{}やreturnを省略できる

```javascript
// 従来のfunctionを使った書き方
var plus = function(x, y) {
  return x + y;
};
 
// アロー関数
let plus = (x, y) => {
  return x + y;
};

// 単一式の場合はブラケットやreturnを省略できる
let plus = (x, y) => x + y;
```

* **`this`は関数が定義されたスコープにおける`this`を引き継ぐ**
これに対し、functionによる関数定義では、それぞれの関数がそれ自身の thisの値を新たに定義していた。(コンストラクターでは新しいオブジェクト、 strict モードでの関数呼び出し時はundefined、関数が"オブジェクトのメソッド" として呼び出された場合はそのオブジェクト、など)

* リテラルを返す場合には()で囲む必要がある。（そうでないと波括弧の中は文としてパーシングされてしまう。)

```javascript
var func = () => ({ foo: 1 });）
```

**アロー関数はSafariは未対応なので要注意**

## 分割代入
一度に複数の変数に、複数の値を代入できる。

```javascript
var name = Izmeal;
var age  = 21;
```

を

```javscript
var [name, age] = ['Koyabu', 20];
```

とできる


## 配列展開

関数の呼び出し、配列への代入、構造化代入に対して、`...`により、配列を展開して用いる事ができる

```javascript
var array = [1, 2, 3]
function f(x, y, z) { }
f(...array);
//f(1, 2, 3)という引数での関数fの呼び出しと同義

[...array, 4, 5, 6]
//[1, 2, 3, 4, 5, 6]となる
var x
var y
var z
var variables = [x, y, z]
[a, b, ...variables] = [1, 2, 3, 4, 5];
// a = 1, b = 2, x = 3, y = 4, z = 5とした場合と同じ
```

## 可変長引数

```
function f(x, ...ys) {
    console.log(x, ys);
}
f(2, 3, 5);
//=> 2 [ 3, 5 ]
```

## デフォルト引数

```javascript
function multiply(a, b = 1) {
  return a*b;
}
multiply(5); // 5
```

のように引数の()括弧内で代入を行うことで、デフォルト値を設定できる

## テンプレート文字列

``で文字列を囲むことで、文字列内での変数展開が${}で行え、改行もそのまま反映できる

```javascript
var name = 'Koyabu'

var hello = `My name is
${name}`
console.log(hello)
//=>My name is 
//Koyabu
```