ES6マラソン・1 〜BabelでES6(Class,let,const,DefaultParameter,Destructuring)がどのようにトランスパイルされるか試して理解する〜

# ES6マラソン・1 〜BabelでES6(Class,let,const,DefaultParameter,Destructuring)がどのようにトランスパイルされるか試して理解する〜

今ちょっとES6を使う機会があってお勉強しております。
今回理解したいのはBabelでトランスパイルされたJSです。
書き出されたそれが何を記述しているのかを把握することで「あ〜なるほどなこういう動きするんだ」と思うのがゴールです。僕の。
なので、ES6から導入されるものを書いて眺めようというちょっとうるさい記事です。



今回みたのは、

 - Class
 - let
 - const
 - Default Parameter
 - Destructuring

## **Babel**
[Babel](https://babeljs.io/)
・ESトランスパイラツール。ES5、ES3に変換してくれる。(他にライブラリを読み込み、ビルド不要でES6を利用できるESポリフィルがある。)
・使う理由はES6の標準化まで長い期間かかる為。coffeeやTSなどのビルドプロセスが当たり前になってきている為。ってこのまえ登壇していたサイボーズのES6太郎さんっていう[この本](http://gihyo.jp/magazine/wdpress/archive/2015/vol87)書いた人が仰ってた
・ES6対応しないIE11がこれから先4年は生きる為
・今トランスパイラを使い続ければ標準化した際に外せばいいだけ


![スクリーンショット 2015-08-30 8.46.57.png](https://qiita-image-store.s3.amazonaws.com/0/64377/ade3d13d-2726-b9df-146d-7f5410a43b69.png)

## **Class**

moritaクラスのインスタンスから関数を実行する単純なものを作ってどのようにトランスパイルされるかみてみようと思います。

[demo](https://babeljs.io/repl/#?experimental=true&evaluate=false&loose=true&spec=false&code=class%20morita%20%7B%0A%20%20constructor(firstName)%7B%0A%20%20%20%20%20%20this.firstName%20%3D%20firstName%3B%20%0A%20%20%20%20%20%20this.lastName%20%3D%20%60kenji%60%0A%20%20%20%20%20%20this.get%20%3D%20()%3D%3E%7B%0A%20%20%20%20%20%20return%20this.firstName%20%2B%20this.lastName%3B%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%0Alet%20firstName%20%3D%20new%20morita('morita')%3B%0AfirstName.get())

```js:es6
class morita {
  constructor(firstName){
   this.firstName = firstName;
   this.lastName = 'kenji';
   this.get = ()=>{
    return this.firstName + this.lastName;
    }
  }
}
let firstName = new morita('morita');
firstName.get()//moritakenji
```

Classを書くとこのようにトランスパイルされるみたいです。

```js:javascript:トランスパイラされたJS
'use strict';

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }

var morita = function morita(firstName) {
  var _this = this;

  _classCallCheck(this, morita);

  this.firstName = firstName;
  this.lastName = 'kenji';
  this.get = function () {
    return _this.firstName + _this.lastName;
  };
};

var firstName = new morita('morita');
firstName.get();
```

何か長いところがあります。

```js:なにやら長いところ
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
```
ここは何しているのでしょうか整形してみます。

```js
function _classCallCheck(instance, Constructor){
 if (!(instance instanceof Constructor))
  { throw new TypeError('Cannot call a class as a function'); } 
}
...
  _classCallCheck(this, morita);
```
thisを第一引数として渡して、class名のmoritaを第二に渡して
thisは本当にこのコンストラクタか評価しているようです。

## **let**

letは同じ実行コンテキスト内でユニークな変数として宣言します


同じスコープブロック内で使ってみると
**Duplicate declaration "x"**のエラーでます。

![スクリーンショット 2015-08-30 12.50.44.png](https://qiita-image-store.s3.amazonaws.com/0/64377/767e7720-45f8-211e-38a4-787dbd785099.png)

[demo](https://babeljs.io/repl/#?experimental=true&evaluate=false&loose=true&spec=false&code=function%20morita()%7B%0A%20%20let%20x%3B%0A%20%20x%3B%0A%20%20x%20%3D%20'kenji'%0A%7D)
同じブロック内で定義したのでエラーでます。

```js:ES6
function morita(){
  let x;
  x;
  x = 'kenji'
}
```

```js:トランスパイラされたjs
'use strict';

function morita() {
  var x = undefined;
  x;
  x = 'kenji';
}
```

letはvarとして変換され、宣言だけだと初期値にはundefinedが明示的に代入されるみたいです。

## **const**
定数は読み取り専用(上書きや再宣言はError)

```js:ES6
function morita(){
  const x = 'kenji';
  const x; '足させてお願い・・';//再宣言。erepl: Unexpected token (3:9)
}
morita()//エラー箇所で止まるのでトランスパイルされない
```
```js:ES6
function morita(){
  const x = 'kenji';
  x =+ '!!足してくれたのね!!';//Error repl: Line 3: "x" is read-only
  console.log(x)
}
morita();//エラー箇所で止まるのでトランスパイルされない
```
read-onlyって出ます。

こちらはエラー出ないでトランスパイルされますが、

```js:ES6
function morita(){
  const x = 'kenji';
  x +  'そろそろ足させてお願い・・';//だから定数だって
}
morita()//undefined
```
undefinedです。
また、constがvarに変換されていることが確認できます。
「定数」なのにvarになっちゃうと代入可能かどうか分からない。。

```js:js
'use strict';

function morita() {
  var x = 'kenji';
  x + 'そろそろ足させてお願い・・';
}
morita();//undefined
```
Babelではエラーで無いけど。。
Babelの役割はES5やES3の記述に変換することであってErrorはき出すのではないからだね。

調べたら[ESLintのドキュメント](http://eslint.org/docs/rules/)に書いてあった。
[no-const-assign](http://eslint.org/docs/rules/no-const-assign)で設定できますね。




## **Default Parameter**
デフォルトパラメーターは関数の仮引数の箇所で初期化できるものです。

[demo](https://babeljs.io/repl/#?experimental=true&evaluate=false&loose=true&spec=false&code=function%20get(firstName%20%3D%20'morita'%2C%20lastName%20%3D%20'kenji')%7B%0A%20%20%0A%7D)

```js:babel
function get(firstName = 'morita', lastName = 'kenji'){
  
}
```
ここまでやって何がされているのかソース見てみた

```js:js
'use strict';

function get() {
  var firstName = arguments.length <= 0 || arguments[0] === undefined ? 'morita' : arguments[0];
  var lastName = arguments.length <= 1 || arguments[1] === undefined ? 'kenji' : arguments[1];
}
```

渡ってきた引数が0かundefinedが初期値だったら..```任意の値``` それ以外だったら```arguments[0]```
仮引数のところには書かないで、argumentsオブジェクトで実際の引数を参照、実行コンテキスト内に代入されるんですね。

[default parameter・英語](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters)
[argumentオブジェクト・MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions_and_function_scope/arguments)

こーゆーことできるんだな。楽だな。いままでvar arrayって箱つくってたもんな。。

```js:ES6
function add(value,array = []){
  array.push(value);
  return array
}
add(4);//[4]
add(5);//[5]
```
[demo](https://babeljs.io/repl/#?experimental=true&evaluate=false&loose=true&spec=false&code=function%20add(value%2Carray%20%3D%20%5B%5D)%7B%0A%20%20array.push(value)%3B%0A%20%20return%20array%0A%7D%0Aadd(4)%3B%2F%2F%5B4%5D%0Aadd(5)%3B%2F%2F%5B5%5D)






## **Destructuring**
なんて？
Destructuring[デストラクチャリング(非構造化)]
[ality – JavaScript and more](http://www.2ality.com/2015/01/es6-destructuring.html)
[babeljs.io/docs/learn-es2015](https://babeljs.io/docs/learn-es2015/)

①last matching

```js:ES6と一部トランスパイルされたjs
//ex1
let [x] = ["morita"];
console.log([x]);//['morita']

//ex2
let [x] = ["morita"];
console.log(x);//morita

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

//ex3 after
"use strict";
var _ref = [1, 2, 3];//_refという変数に格納される
var a = _ref[0];
var b = _ref[2];//commaを含めて何番目か[(0),(1),(2)]の[2]
console.log(b);//3

//ex4 
var [a,,,,,b] = [1,2,3]; //commaの数増やす
console.log(b)//undefined //[1,2,3,undefined,undefined(ココ)]ココを参照しようとしている

//ex4 after
"use strict";
var _ref = [1, 2, 3];
var a = _ref[0];
var b = _ref[5];//5番目にbが割り当てられている

console.log(b);//undefined

//ex5
let [,,,y] = ['a','b','c','d','e']//

//ex5 after
'use strict';
var _ref = ['a', 'b', 'c', 'd', 'e'];
var y = _ref[3];
y//3

```
②object matching

```js:ES6
//ex1 babel
let {a: fa, b:he, c:{a:le}, d:se} = hagehageget

//ex1 after
"use strict";

var _hagehageget = hagehageget;
var fa = _hagehageget.a;
var he = _hagehageget.b;
var le = _hagehageget.c.a;
var se = _hagehageget.d;
```
③Can be used in parameter position

```js
//ex1 babel
function g({name: x}) {
  console.log(x);
}
g({name: 5})//そのまま渡している


//ex1 after
"use strict";
function g(_ref) {
  var x = _ref.name;
  console.log(x);
}
g({ name: 5 });//5
```

④Fail-soft destructuring

```js:ES6
//ex1
var [a] = [];
a === undefined;//true


//ex1 after
"use strict";
var _ref = [];
var a = _ref[0];
a === undefined; //true

```

⑤Fail-soft destructuring with defaults

```js:ES6

//ex1
var [a = 1] = [];
a === 1;//true

//ex1 after
"use strict";
var _ref = [];
var _ref$0 = _ref[0];
var a = _ref$0 === undefined ? 1 : _ref$0;
a === 1; //true
```

Object matching
[ECMAScript 6 and Destructuring Assignment](http://ariya.ofilabs.com/2013/02/es6-and-destructuring-assignment.html)
上記を参照に。重複するかもしれないけど記しておく

>text Variables can be initialized in one go. The following two lines have the same effect, the first one is employing an array pattern.

```js:ES6
//2つは同じ意味
let [a,b,c] = ['fafa','fefe','hoho'];
var a = 'fafa', b='fefe', c='hoho'; 

//array patternという初期化処理。
//マッチした箇所に代入されるstring
```
**Object Pattern**

```js:ES6
//ex1 babel
function today() { return { d: 6, m: 2, y: 2013 }; }
var { m: month, y: year } = today(); // month = 2, year = 2013

//ex1 after
"use strict";
function today() {
  return { d: 6, m: 2, y: 2013 };
}
var _today = today();//関数名が「_変数」になっている
var month = _today.m;//オブジェクトプロパティを参照代入している
var year = _today.y;
// month = 2, year = 2013

//ex2 babel
let obj = { first: 'Jane', last: 'Doe' };
let {first:i,last:s} = obj;//オブジェクトをmatchするところに割り当てている

//ex2 after
'use strict';
var obj = { first: 'Jane', last: 'Doe' };
var i = obj.first;
var s = obj.last;
console.log(i)//Jane
console.log(s)//Doe
```

今回の記事書いていて感じたことは地味にDestructuringが結構大事なような気がしました。
こちらの[JavaScript and more](http://www.2ality.com/2015/01/es6-destructuring.html)って記事いいよ。

あと全然関係ないですけど、
この前怖い夢見て、
その夢が、母親が「この世からいなくなる」っていう夢だったんですけど、
要は「死ぬ」みたいな、、
次の日母親から電話掛かってきたんですよ！
まさか！！？？この世から居なくなったのか？と思うじゃないですか？
タイミングがタイミングだし、
おそるおそる取るじゃないですか？電話。
そしたら

**「けんちゃん、トマトジュース飲んでる？」**て。
健康にいいよ？て。





参照
[WEB+DB PRESSvol87「今すぐ活かす!最新JavaScript」](http://gihyo.jp/magazine/wdpress/archive/2015/vol87)
[fail-fast object destructuring (don't add more slop to sloppy mode)](https://esdiscuss.org/topic/fail-fast-object-destructuring-don-t-add-more-slop-to-sloppy-mode)
[ECMAScript 6 and Destructuring Assignment](http://ariya.ofilabs.com/2013/02/es6-and-destructuring-assignment.html)
[http://www.2ality.com/2015/01/es6-destructuring.html](http://www.2ality.com/2015/01/es6-destructuring.html)
[Learn ES2015](https://babeljs.io/docs/learn-es2015/)