NodeSchoolのtower-of-babelを解いてみる #2

#はじめに

[NodeSchoolのtower-of-babelを解いてみる #1](http://qiita.com/naoyamuto/items/de1534f035a066c6f20e)の続きになります。

# COMPUTED PROPERTY
- ES6からオブジェクトのプロパティ名に式を評価できるようになった
    - 今まではプロパティ名に動的な値を入れる際は下記のようにしていた

```js
var prop = "hoge";

var obj = {};
obj[prop] = "fuga";

```

- ES6からは下記のようになる。これを`Computed Property`と呼ぶ。

```js
var prop = "hoge";

var obj = {
 [prop]: "fuga"
};
```

## 問題
- 以下のオブジェクトをComputed Propertyを使って書き換える
- 一時変数を全く使わずに表現する

```js
var evenOrOdd = +process.argv[2];
var evenOrOddKey = evenOrOdd % 2 === 0 ? "even" : "odd";
var sum = +process.argv[3] + evenOrOdd;
var obj = {};
obj[evenOrOddKey] = evenOrOdd;
obj[sum] = sum;
console.log(obj);
```

```program.js

console.log({
  [+process.argv[2] % 2 === 0 ? "even" : "odd"]: +process.argv[2],
  [+process.argv[2] + +process.argv[3]] : +process.argv[2] + +process.argv[3]
});

```

# ITERATOR FOR OF
- ES6から新しく`for of`という文法が追加
  - これまでの`for in`文と異なり、繰り返し可能なもの(`Iterable`)なものであれば`for of`で繰り返すことが可能
    - `Iterable`なものを作るには`Symbol.Iterator`を用いる。定義は下記。

```js

// 1000までの値を返すfibonacciを作る
var fibonacci = {
// Symbol.iteratorを持つメソッドを持つオブジェクトにする
[Symbol.iterator]() {
  let currentValue = 0, nextValue = 1;
  // iteratorオブジェクトは nextメソッドを持つオブジェクトを返す
  return {
    next() {
      // nextの中では返す値(value)と次で終わりかどうかを示すプロパティ(done)を返す
      if (nextValue > 1000) return { done: true };
      [currentValue, nextValue] = [nextValue, currentValue + nextValue];
      return { done: false, value: currentValue };
    }
  }
}
}

for (var n of fibonacci) {
console.log(n);
}

```
## 問題
- 1から始まり、コマンドライン引数に受けとった数までカウントする`FizzBuzz`問題を使って`for of`ループで回す
- JSで書いたFizzBuzzコード。

```fizzbuzz.js

for (var i = 1; i< 20; i++) {
  if(i % 3 == 0 && i % 5 == 0 ) {
    console.log("FizzBuzz");
  }
  else if(i % 3 == 0) {
    console.log("Fizz");
  }
  else if(i % 5 == 0) {
    console.log("Buzz");
  }
  else {
    console.log(i);
  }
}

```
- これを`for of`構文で書いてみる。
- `Iterator`オブジェクトはnextメソッドを持つオブジェクトを返す
- `next()`の中ではvalueと次で終わりかどうかを示すプロパティ(done)を返す
  - 計算を継続させたいときは`{done:false}`を返却し、逆に終了条件を満たすときは`{done:true}`を返却する。

```program.js

const max = process.argv[2];
let FizzBuzz = {
  [Symbol.iterator]() {
    //FizzBuzzの計算
    let num = 1;
    return {
      next() {
        if(num > max) {
          return {done: true};
        }
        let value = num;
        if(num % 3 == 0 && num % 5 == 0) {
          value = "FizzBuzz";
        }
        else if(num % 3 == 0) {
          value = "Fizz";
        }
        else if(num % 5 == 0) {
          value = "Buzz";
        }
        num++;
        return {done: false, value: value};
      }
    }
  }
}

for(var n of FizzBuzz) {
  console.log(n);
}

```

# GENERATOR
- `Iterator`オブジェクトを作りやすくするための`generator`の扱いを学ぶ。
- `generator`を使った例は下記。
  - 変更点は関数に`function*`が入っていることと`return`が`yield`に変わっていること。

```js
let fibonacci = function*(){
  let currentValue = 0, nextValue = 1;
  while (currentValue < 1000) {
    // ここでdestructuringで値をswapさせる。
    [currentValue, nextValue] = [nextValue, currentValue + nextValue];
    // yieldで値を返す
    yield currentValue;
  }
}();

for (var n of fibonacci) {
  console.log(n);
}
```

# 問題
- 前回作った`FizzBuzz`問題を`generator`を使って書き換える

```program.js
const max = process.argv[2];
let FizzBuzz = function*(){
    //FizzBuzzの計算
    let num = 1;
    while (num <= max) {
      let value = num;
      num++;
      if (value % 3 == 0 && value % 5 == 0) {
        value = 'FizzBuzz';
      }
      else if (value % 3 == 0) {
        value = 'Fizz';
      }
      else if(value % 5 == 0) {
        value = 'Buzz';
      }
      yield value;
    }
}();

for(var n of FizzBuzz) {
  console.log(n);
}
```

# DESTRUCTURE
- デストラクチャリング、日本語でいうと分配束縛と呼ばれる機能
- 今までの値をswap方法は以下のように`temp`という一時変数に入れてから値を交換していた

```js
var hoge = 123;
var fuga = 456;

// 値をswapする
var tmp = hoge;
hoge = fuga;
fuga = tmp;

```

- デストラクチャリングを使ったら、以下のように、配列に値を入れて左辺で交換するだけで実現できる

```js
var hoge = 123;
var fuga = 456;

// 値をswapする
[fuga, hoge] = [hoge, fuga];
```

## 問題
- 以下のJSONをデストラクチャリングを使って書き換える

```js
var json = {
  "name": {
    "first": "Yosuke",
    "family": process.argv[2]
  },
  "birth": {
    "year": 1982,
    "month": 12,
    "day": process.argv[3]
  }
};

// ここでデストラクチャリングを使ってname.familyをfamilyNameに。
// birth.day を birthDay に束縛してください。

console.log(familyName);
console.log(birthDay);
```

```program.js

var json = {
      "name": {
        "first": "Yosuke",
        "family": process.argv[2]
      },
      "birth": {
        "year": 1982,
        "month": 12,
        "day": process.argv[3]
      }
};

//デストラクチャリングでオブジェクトの値を取得
var {name: {family: familyName}, birth: {day: birthDay}} = json;

console.log(familyName);
console.log(birthDay);

```

# ARROW FUNCTION
- ES5から新たにアロー関数が仕様として追加された
  - アロー関数を使うことで無名関数を短く記述することが可能に

```js
//今までの記述方法
setTimeout(function(){
     console.log('Test');
   }, 100);

//アロー関数を用いた記述方法
setTimeout(()=>{console.log('Test');}, 100);
```

## 問題
- コマンドライン引数から任意の数の文字列を受け取り、最初の一文字だけ取得して結合するための関数を作る
   - 例えば`["Hello", "Arrow", "Function"]`の場合、結果として`HAF`という文字列が得られる
- まずはアロー関数を使わないで書いてみる

```js
var inputs = process.argv.slice(2);

var result = inputs.map(function(str){
  return str[0];
}).reduce(function(a,b) {
  return a + b ;
});

console.log(result);
```

- アロー関数で書き換えてみる

```program.js
var inputs = process.argv.slice(2);

var result = inputs.map((str) => str[0])
                   .reduce((a,b) => a + b);
console.log(result);
```


# REST AND SPREAD
- 可変長なパラメータを受け取る関数を実現する場合、今までは`arguments`と呼ばれる配列ライクなオブジェクトを扱うことで実現されていた
  - しかし`arguments`は配列ではないため、配列のメソッドである`map`や`reduce`は使えなかった
- ES6からは`arguments`を使わなくても引数に`...`をつけることで可変長パラメータの処理を実現できるように。以下、例

```js
var sum = function(...args){
  return args.reduce( (sum, n) => sum + n );
};

var array = [1, 2, 3, 4];
// 配列から sum(1,2,3,4) で呼び出すのと同じ
console.log(sum(...array)); // 10
```

## 問題
- `Rest`パラメータを使って平均を取る関数を作る

```program.js

var args = process.argv[2].split(",");
    args = args.map((arg)=> +arg);

// ここに平均を取るavg関数を作る、作る際にはRESTパラメータを利用すること。
function avg(...args) {
  return args.reduce((a, b) => a+b) / args.length;
}

console.log(avg(...args));

```

![image](https://qiita-image-store.s3.amazonaws.com/0/37467/8d2e80f0-53a4-d225-4ae9-ca6caa03c9ef.png)