ES6を少しだけモミモミしてみる

##はじめに
先日勉強会に参加したところES6の話題が多かった印象を受けたので、勉強会で出てきた言葉を元に少し調べました。

js自体がまだちゃんと書けていない私としては、ES6を学ぶのはしんどいですが、いつか輝く為に少しずつ学ぼうと思います。


##Template literal

Template literalを使うと、文字列の連結をスッキリかけるようになります。
``+``や``join()``を使わなくてもいいのです！

やり方は、``${}``と`` ` ``(バッククオート)を利用して文字列の連結を行います。<br>
バッククオート内の``${}``の中が評価され、その結果が置き換わります。


#####ES5
```
var str1 = 'スーパー';
var str2 = '合体';

var str = 'Template literalで文字列の' + str1 + 'の' + str2 + '!';

console.log(str);//Template literalで文字列のスーパーの合体!
```

#####ES6

```
var str1 = 'スーパー';
var str2 = '合体';
 
var str = `Template literalで文字列の${str1}の${str2}!`;
 
console.log(str); //Template literalで文字列のスーパーの合体!
```
###式を評価して表示
``${}``の中には変数だけでなく式をいれることができます。

#####ES5
```
var str = 5 * 5 + "は" + (5 + 5 + 5 + 5 + 5) + "!";
```

#####ES6
```
var str = `${5*5}は${5+5+5+5+5}!`;
```


##Default parameters

JavaScriptでの、関数の引数は、undefinedが初期値となります。<br>
ES5では、引数の初期値を自由に設定することができなかった為、関数内で引数をチェックして、
undefinedなら初期値を設定するようなことをやってました。

ES6からは、下記例のように引数の初期値を設定できます。


#####ES5
```
function defaultParameters(a) {
  var b = arguments.length <= 1 || arguments[1] === undefined ? 'あるとうれしい！' : arguments[1];

  return a + b;
}

var str = defaultParameters('初期値が'); 
console.log(str); //初期値があるとうれしい！
```

#####ES6
```
function defaultParameters(a, b = 'あるとうれしい！') {
  return a + b;
}

var str = defaultParameters('初期値が'); 
console.log(str);//初期値があるとうれしい！
```

##Rest parameters

今まで引数が可変の（いくつ渡ってくるかわからない）場合、argumentsを使用してやりくりしていましたが、Rest parametersを使用すれば、引数を可変長で受け取ることができます。

#####ES5
```
function rest() {
  for (var _len = arguments.length, values = Array(_len), _key = 0; _key < _len; _key++) {
    values[_key] = arguments[_key];
  }

  console.log(values);
}

rest(1, 2, 3);//[1,2,3]
```

#####ES6
```
function rest(...values) {
  console.log(values);
}

rest(1,2,3);//[1,2,3]
```

Rest Parametersのルールとして、引数の**最後で渡す**必要があります。
下記の場合、可変長引数の``...values``が第１引数として設定されている為、エラーとなります。


```
function rest(...values,value) {
  console.log(values);
}

```

下記ばOK。

```
function rest(value,...values) {
  console.log(values);
}

```

##Spread operator

Spread operatorを使うと配列同士を結合したりする場合に便利です。

#####ES5
```
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
var arr3 = [].concat(arr1, arr2);

arr1.push.apply(arr1, arr2);

console.log(arr1); // [0, 1, 2, 3, 4, 5]
console.log(arr3); // [0, 1, 2, 3, 4, 5]

```


#####ES6
```
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
var arr3 = [...arr1,...arr2];

arr1.push(...arr2);

console.log(arr1); // [0, 1, 2, 3, 4, 5]
console.log(arr3); // [0, 1, 2, 3, 4, 5]
```

##Destructuring

Destructuringは分割代入という、新しい変数代入の方法です。

#####配列で受け取る
```
var [a,b] = [1,2];
console.log(a,b)//1 2

var [a, b, ...rest] = [1, 2, 3, 4, 5];
console.log(a,b,rest)//1 2 [3,4,5]

```
#####関数の戻り値で受け取る
```
var [a,b] = (function(){return [1,2];})();
console.log(a,b)//1 2

```

#####一部省略や、デフォルト値を設定する
```
var [a,,[b,c],d=5] = [1,2,[3,4],5];
console.log(a,b,c,d);//1,3,4,5

```
####オブジェクトで受け取る
```
var obj = {name:'太郎',sex:'男',age:30};
//必要なプロパティだけ代入
var {name:n,age:a} = obj;

console.log(n,a)//太郎 30
```

上記をES5で書くとこんな感じ。こっちのほうがわかりやすいような気がするのは、私が未熟なせいでしょう。。。
#####ES5

```
var obj = { name: '太郎', sex: '男', age: 30 };
var n = obj.name;
var a = obj.age;

console.log(n, a); //太郎 30
```

##Blockscope

###let
letを使うことで、関数スコープでなく、ブロックスコープを使用することができます。

#####letを使った場合
```
if(true){
  let a = 1;
  console.log(a);//1
}

console.log(a);//error

```

#####varを使った場合
```
if(true){
  var a = 1;
  console.log(a);//1
}

console.log(a);//1
```

ES5の場合は即時関数を利用してスコープをつくってました。

```
var a = 0;
(function(){
	var a = 1;
	console.log(a);//1
})();
console.log(a);//0

```

ES6はletを使うことでスコープの範囲がわかりやすくなりました。

```
var a = 0;
{
  let a =1;
  console.log(a);//1
}
console.log(a);//0
```

###関数宣言をブロックスコープ内に定義

関数宣言もブロックスコープ内に定義することができます。

```
{
  function block(){return 1;}
  console.log(block());//1
  {
    function block(){return 0;}
    console.log(block());//0
  }
  console.log(block());//1
}
```

##const
定数を定義することができます。

```
const a = 1;
console.log(a);//1

//再定義はエラーとなる
const a = 1;//error

//代入は無視される
a = 0;
console.log(a);//1
```

##Arrow Function

アロー関数を使用することで、関数の定義が短くかける。


#####ES5
```
[1, 2, 3].map(function (v) {
  console.log(v);
});
```

#####ES6
```
//引数が一つの時には「(v)の()」を省略できる
[1,2,3].map(v=>{console.log(v);});

//下記でもOK
//[1,2,3].map((v)=>{console.log(v);});
```

###Arrow Functionのthis
アロー関数のthisは、関数が実行されれたときに決まるのではなく、関数が定義されたときに決まる。

アロー関数を使うことで、selfとか_thisとかを使わないくて済むようになる。

```
function Myfunc(){  
  this.name = '太郎';
  setTimeout(()=>{
    console.log(this.name);//太郎
  })
}

new Myfunc();
```

従来のfunctionで定義した場合

```
function Myfunc(){
    
  this.name = '太郎';
  
  setTimeout(function(){
  	//thisはwindowを参照する
    console.log(this.name);//undefined
  },100)
}

new Myfunc();

```

##Async関数(ES7)

async、awaitを使うと非同期処理を、まるで同期処理を書いているように書けます。

下記の例のように、``await``を追加した関数は、その処理が終わるまで次の処理に移りません。<br>
awaitを使う場合は、awaitを使う関数を``async function``をにする必要があります。

※このあたりまだちゃんと理解できていない為、記載の表現に誤りがあるかも。。。


```
function asyncGet(req, wait){ 
  return new Promise(
    resolve => setTimeout(function(){resolve(req)}, wait)
  );
}

async function test(){
    console.log(await asyncGet("リクエスト1", 1000));
    console.log(await asyncGet("リクエスト2", 100));
    console.log(await asyncGet("リクエスト3", 3000));
    console.log(await asyncGet("リクエスト4", 200));
    
    //リクエスト1
	//リクエスト2
	//リクエスト3
	//リクエスト4
};

test();
```

いままでは下記のように書いてました。
上記にくらべると冗長な感じがしますし、
async、awaitを使ったほうがコードの見通し良くなった気がします。

```
function asyncGet(wait){ 
  return new Promise(
    resolve => setTimeout(function(){resolve()}, wait)
  );
}

function test(){
   asyncGet(1000)
   .then(function(){
    console.log("リクエスト1");
     return asyncGet(1000);
   })
   .then(function(){
      console.log("リクエスト2");
     return asyncGet(100);
   })
    .then(function(){
      console.log("リクエスト3");
     return asyncGet(3000);
   })
    .then(function(){
      console.log("リクエスト4");
     return asyncGet(200);
   });
};

test();
```

##終わり
ES6からはClassも使えるようになり、色々やれることが増えるようです。
記載の内容以外にも沢山便利な機能があるようなので、今後も調べていこうと思います。