[Node.js] ES6 Arrow Function をいろんな書き方で書いてみた

Node.js 4.0.0が来たので、勉強がてら（これ始める前は4.0.0で〜とか思ってたけど、見てみたら4.1.1来てたのか...）

本記事は `Node.js 4.1.1` で試しています

```js
> process.version
'v4.1.1'
```

## Arrow function

### 単純な使い方(void)
```js
var a = () => {
  console.log(1);
};
a();
//=> 1

let b = () => {
  console.log(2);
};
b();
//=> 2
//=> 注意これはインタプリタの場合だと成功しますが、 node app.js のように実行する場合は失敗します
//=> [追記] use strictを使えば問題なかった

var c = () => console.log(3);
c();
//=> 3

let d = () => console.log(4);
d();
//=> 4
//=> 注意これはインタプリタの場合だと成功しますが、 node app.js のように実行する場合は失敗します
//=> [追記] use strictを使えば問題なかった

// 失敗例
$ node b.js
let b = () => console.log(2);
^^^

SyntaxError: Block-scoped declarations (let, const, function, class) not yet supported outside strict mode
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:413:25)
    at Object.Module._extensions..js (module.js:452:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:475:10)
    at startup (node.js:117:18)
    at node.js:951:3
```

### returnをしたい場合

```js
var a = () => {
  return 1;
};
console.log(a());
//=> 1

var b = () => 2;
console.log(b());
//=> 2

var b = () =>
  2;
console.log(b());
//=> 2

var c = () => return 3;
//=> SyntaxErrorです
var c = () => return 3;
              ^^^^^^
SyntaxError: Unexpected token return
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:413:25)
    at Object.Module._extensions..js (module.js:452:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:475:10)
    at startup (node.js:117:18)
    at node.js:951:3
```

### 引数をつけたい場合

```js

var hoge = (a) => a * 2;

console.log(hoge(5));
//=> 10
console.log(hoge(5 * 2));
//=> 20


var hoge = (cb) => cb();

hoge( () => console.log(1) );
//=> 1

hoge( () =>
  console.log(1)
);
//=> 1

hoge(
  () => console.log(1)
);
//=> 1

hoge( ()
  => console.log(1)
);
//=>
  => console.log(1)
  ^^

SyntaxError: Unexpected token =>
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:413:25)
    at Object.Module._extensions..js (module.js:452:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:475:10)
    at startup (node.js:117:18)
    at node.js:951:3
```

### 引数を受け取って更にその中で関数を実行させる場合

```js
let arr = ['abc', 'de', 'f'];

console.log(arr.map(v => v.toUpperCase()));
//=> [ 'ABC', 'DE', 'F' ]

var sum = (arr) =>
  arr.reduce( (a, b) => a + b );

console.log(sum([1, 2, 3, 4, 5, 6, 7, 8, 9]));
//=> 45

var fibo = (n) => {
  if (n < 2) return n;
  return fibo(n - 2) + fibo(n - 1);
};

console.log(fibo(10));
//=> 55

var fibo = (n) =>
  if (n < 2) return n;
  return fibo(n - 2) + fibo(n - 1);

console.log(fibo(10));
//=>
  if (n < 2) return n;
  ^^

SyntaxError: Unexpected token if
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:413:25)
    at Object.Module._extensions..js (module.js:452:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:475:10)
    at startup (node.js:117:18)
    at node.js:951:3
```

### デフォルト引数を使ってみたい場合

```js
var f = (x, y = 7) => x + y;
console.log(f(1));
//=>
var f = (x, y = 7) => x + y;
              ^

SyntaxError: Unexpected token =
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:413:25)
    at Object.Module._extensions..js (module.js:452:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:475:10)
    at startup (node.js:117:18)
    at node.js:951:3
```

残念(◞‸◟)

### レキシカル this は？

```js
let arr = [1, 2, 3];
arr.forEach(v => console.log(v, this));
//=>
1 {}
2 {}
3 {}

arr.forEach(function(v) {
  console.log(v, this);
});
//=>
1 undefined
2 undefined
3 undefined

arr.forEach(function(v) {
  console.log(v, this);
}.bind(this))
//=>
1 {}
2 {}
3 {}
```

この `this` が関数定義時に決まっているっぽいので、それを考えると例えば下記のような結果になるという事だろうか？

```js
function hoge(target, evtName) {
  target.addEventListener(evtName, function() {
    console.log(this); //=> targetがthisになる
  });
}

var hoge = (target, evtName) => {
  target.addEventListener(evtName, () => console.log(this)); //=> hogeがthisになる
}
```

### 即時実行関数をしたい場合

```js
(() => console.log(1))();
//=> 1

((a, b) => console.log(a, b))(1, 'hoge');
//=> 1 'hoge'

(=> console.log(1))();
//=> SyntaxErrorです
(=> console.log(1))();
 ^^

SyntaxError: Unexpected token =>
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:413:25)
    at Object.Module._extensions..js (module.js:452:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module.runMain (module.js:475:10)
    at startup (node.js:117:18)
    at node.js:951:3
```

### Block Scopeどうなってんの？

```js
{
  (() => console.log(this))();
}
//=> {}

```

上記のコードは下記のように解釈されているっぽい

```js
(function() {
  (function() { console.log(this); })();
})();
```

ともすると、JSONと読み間違えたりしないだろうか :question: :question: 

#### [余談] require

```
$ ls
> b.json          c.js
```

```json:b.json
{
  "id": 1
}
```

```js:c.js
{
  (() => console.log('cのファイル'))();
}
```

```js:a.js
{
  var b = require('./b');
  var c = require('./c');
  console.log(b);
  console.log(c);
}
```
```
$ node a.js
cのファイル
{ id: 1 }
{}
```

`b.json` と `c.js` の拡張子を入れ替えます

```js:b.js
  "id": 1
      ^

SyntaxError: Unexpected token :
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:413:25)
    at Object.Module._extensions..js (module.js:452:10)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Module.require (module.js:365:17)
    at require (module.js:384:17)
    at Object.<anonymous> (~~/a.js:2:11)
    at Module._compile (module.js:434:26)
    at Object.Module._extensions..js (module.js:452:10)
```

```js:c.json
module.js:463
    throw err;
    ^

SyntaxError: /Development/ruby_work/vagrants/vagrant/virtualbox/vbox-develop/c.json: Unexpected token (
    at Object.parse (native)
    at Object.Module._extensions..json (module.js:460:27)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Module.require (module.js:365:17)
    at require (module.js:384:17)
    at Object.<anonymous> (/Development/ruby_work/vagrants/vagrant/virtualbox/vbox-develop/a.js:3:11)
    at Module._compile (module.js:434:26)
    at Object.Module._extensions..js (module.js:452:10)
    at Module.load (module.js:355:32)
```

杞憂みたいですね :smiley: 

---
こんな所かな？

とりあえずワンライナーへのサポートが凄い( `return` は抜けるし `{}` は抜いていいし)

これ試して欲しいとかあれば、コメント欄に書いてもらえれば :sunglasses: 
PRを送ってもらっても良いです :exclamation: