ES6メモ

udemyでES6 javascriptを勉強しているのでちょっとしたメモ
教材：[【世界で2万人が受講】JavaScriptエンジニアのためのES6完全ガイド](https://www.udemy.com/javascriptes6/)

# 変数、定数の定義
varでなく、let, constを使う。
変数が`let`, 定数が`const`

# テンプレートリテラル　文字列の連結について
バックティックで囲んで${}の中に変数なり、javascriptの構文を書くことが可能。

```javascript
//バックディックで囲む
function getMessage(){
    return `今年は${new Date().getFullYear()}年です`
}
console.log(getMessage());
```


# forEachメソッド
```javascript
const colors = ['red', 'blue', 'green']
colors.forEach(function(color) {
  console.log(color);
});
//実行結果
//red, blue, green
```
forEachに匿名関数を使わず、定義した関数を呼ぶこともできる。

```javascript
const numbers = [1,2,3,4,5]
let sum = 0
function adder(number){
  sum += number
}
numbers.forEach(adder)  //adder関数を呼ぶ
console.log(sum)  //15
```

# mapメソッド
配列をループしてreturnで戻す。

```javascript
const numbers = [1,2,3]
let doubled= numbers.map(function(number){
  return number* 2
})
console.log(doubled)  //[2, 4, 6]
```
スピードを求める処理

```javascript
var trips = [
  { distance: 34, time: 10 },
  { distance: 90, time: 50 },
  { distance: 59, time: 25 }
];
var speeds = trips.map(function(trip){
  return trip.distance/trip.time
})
console.log(speeds)  //[3.4, 1.8, 2.36]
```

# filterメソッド
配列の中から特定のものを絞り込む

```javascript
var products = [
  {name:'きゅうり', type:'野菜'},
  {name:'バナナ', type:'フルーツ'},
  {name:'セロリ', type:'野菜'},
  {name:'オレンジ', type:'フルーツ'},
]

//フルーツを取得する
let fruits = products.filter(function(product){
  return product.type === 'フルーツ';
})

console.log(fruits)
//0: {name: "バナナ", type: "フルーツ"}
//1: {name: "オレンジ", type: "フルーツ"}
```

# findメソッド(TODO)
特定のデータを探す。

# everyとsomeメソッド(TODO)
# reduceメソッド(TODO)
# アロー関数
### ES5的な書き方の場合
```javascript
const add = function(a,b){
    return a+b;
}
console.log(add(1,2));  //3
```
### ES6の場合
`function`が消えて`=>`を追加

```javascript
const add = (a,b) => {
    return a+b;
}
console.log(add(1,2));    //3
```

### ES6省略した場合
```javascript
const add = (a,b) => a+b;
console.log(add(1,2));   //3
```

### mapと組み合わせた場合
mapでnumbers配列の中身を2倍にするコード

```javascript
const numbers = [1,2,3];
const calc = numbers.map(function(number){
    return 2*number
});
console.log(calc);    // [2, 4, 6]
```
アロー関数を使った場合

```javascript
const numbers = [1,2,3];
const calc = numbers.map((number) => {
    return 2*number
});
console.log(calc);    // [2, 4, 6]
```
評価が1つだけの場合は省略が可能

```javascript
const numbers = [1,2,3];
const calc = numbers.map((number) => 2*number);
console.log(calc);    // [2, 4, 6]

//引数が一つの場合はメソッド引数のカッコも省略が可能
const calc2 = numbers.map(number => 2*number);
console.log(calc2);    // [2, 4, 6]
```

### コールバック関数内のthisについて
ES5的な書き方の場合、bind(this)を指定しなければ、this.teamNameはundeindで参照することができない。

```javascript
const team = {
  members: ['太郎', '花子'],
  teamName: 'スーパーチーム',
  teamSummary: function() {
    return this.members.map(function(member){
      return `${member}は${this.teamName}の所属です。`;
    }.bind(this));  //この部分必要
  }
}
console.log(team.teamSummary());  //["太郎はスーパーチームの所属です。", "花子はスーパーチームの所属です。"]
```
もしくはselfを使う

```javascript
const team = {
  members: ['太郎', '花子'],
  teamName: 'スーパーチーム',
  teamSummary: function() {
    var self = this;    //この部分必要
    return this.members.map(function(member){
      return `${member}は${self.teamName}の所属です。`;
    });
  }
}
console.log(team.teamSummary());  //["太郎はスーパーチームの所属です。", "花子はスーパーチームの所属です。"]
```
ES6のアロー関数ではlexical thisという考え方で`this.teamName`が取得できるらしい

```javascript
const team = {
  members: ['太郎', '花子'],
  teamName: 'スーパーチーム',
  teamSummary: function() {
    return this.members.map((member) =>{
      return `${member}は${this.teamName}の所属です。`;
    });
  }
}
console.log(team.teamSummary());  //["太郎はスーパーチームの所属です。", "花子はスーパーチームの所属です。"]
```

# オブジェクトリテラル
### ES5的な書き方

```javascript
function createBookShop(inventory){
  return {
    inventory:inventory,
    //価格の合計
    inventoryValue: function(){
      return this.inventory.reduce((total,book) => total+book.price,0);
    },
    //タイトルの価格を返す。
    priceForTitle: function(title){
      return this.inventory.find(book => book.title === title).price;
    }
  }
}
```
### ES6的な書き方 

+ keyとvalueが同一の場合、省略ができる
+ 関数functionが省略できる

```javascript
function createBookShop(inventory){
  return {
    inventory,  //inventory:inventory,と同じ
    //価格の合計
    inventoryValue(){  //inventoryValue: function(){ と同じ
      return this.inventory.reduce((total,book) => total+book.price,0);
    },
    //タイトルの価格を返す。
    priceForTitle(title){    //priceForTitle: function(title){と同じ
      return this.inventory.find(book => book.title === title).price;
    }
  }
}
```
```javascript
function createBookShop(inventory){
  return {
    inventory,
    //価格の合計
    inventoryValue(){
      return this.inventory.reduce((total,book) => total+book.price,0);
    },
    //タイトルの価格を返す。
    priceForTitle(title){
      return this.inventory.find(book => book.title === title).price;
    }
  }
}

const inventory = [
  {title: 'PHP入門', price:1000},
  {title: 'javascritp入門', price:1500},
];

const bookshop = createBookShop(inventory)
console.log(bookshop.inventoryValue())    //2500
console.log(bookshop.priceForTitle('PHP入門'))    //1000
```

# 関数のデフォルト引数
```javascript
function makeAjaxRequest(url, method='GET') {
  return method;
}

console.log(makeAjaxRequest('google.co.jp'))  //GET
console.log(makeAjaxRequest('google.co.jp', 'POST'))  //POST
console.log(makeAjaxRequest('google.co.jp', null))  //null
console.log(makeAjaxRequest('google.co.jp', undefined))  //GET
```

# Rest演算子

```javascript
function addNumbers(...numbers) {  //引数が増えても動的に配列に格納できる。
  return numbers.reduce((sum, number) => {
    return sum + number;
  },0)
}
console.log(addNumbers(1,2,3,4));   //10
console.log(addNumbers(1,2,3,4,5)); //15
```

# Spread演算子
```javascript
const defaultColors = ['赤','緑']
const userFavoriteColors = ['オレンジ','黄']
console.log([...defaultColors, ...userFavoriteColors])  //["赤", "緑", "オレンジ", "黄"]
```

# 分割代入（Destructuring）
```javascript
var expense = {
  type:'交際費',
  amount:'4500yen'
}

const {type, amount} = expense  //分割代入できる
console.log(type);    //expense.typeの"交際費"
console.log(amount);  //expense.amountの"4500yen"

const {type:myType, amount:myAmount} = expense
console.log(myType);  //expense.typeの"交際費"
console.log(myAmount);     //expense.amountの"4500yen"
```
## 関数の分割代入
```javascript
var savedFile = {
  extension:'jpg',
  name:'profile',
  size:14040
}

function fileSummary({name, extension, size}) {  //引数は中括弧。savedFileのキーをこのように記述できる。
  return `${name}.${extension}の容量は${size}です`  
}

console.log(fileSummary(savedFile))    //profile.jpgの容量は14040です
```

## 配列の分割代入
```javascript
const companies = [
  'Google',
  'Facebook',
  'Uber'
]

const [name, name2, name3] = companies;  //配列の分割代入
console.log(name);   //Google
console.log(name2);  //Facebook
console.log(name3);  //Uber

const [nam4, ...rest] = companies;  //配列の分割代入rest演算子
console.log(nam4);  //Google
console.log(rest);  //["Facebook", "Uber"]
```

## 配列とオブジェクトを同時に分割代入
配列の中のオブジェクトを抽出

```javascript
const companies = [
  {name: 'Google', location:'マウンテンビュー'},
  {name: 'Facebook', location:'メロンパーク'},
  {name: 'Uber', location:'サンフランシスコ'}
]

const [{location,name}] = companies;  //分割代入
console.log(name);  //Google
console.log(location);  //マウンテンビュー
```

オブジェクトの中の配列を抽出

```javascript
const companies = {
  locations:['マウンテンビュー', 'ニューヨーク', 'ロンドン']
}
const {locations: locs } = companies;  //分割代入
console.log(locs);  //["マウンテンビュー", "ニューヨーク", "ロンドン"]

const [first] = locs;
console.log(first);  //マウンテンビュー
```

```javascript
const companies = {
  locations:['マウンテンビュー', 'ニューヨーク', 'ロンドン']
}
const {locations: [first] } = companies;  //分割代入
console.log(first);  //マウンテンビュー
```
## 分割代入の組み合わせ
```javascript
const points = [
  [4, 5],
  [10, 1],
  [0, 40],
];
testpoint = points.map(point => {
  const [x,y] = point;
  return {x,y}
})
console.log(testpoint)
//0: {x: 4, y: 5}
//1: {x: 10, y: 1}
//2: {x: 0, y: 40}
```

```javascript
const points = [
  [4, 5],
  [10, 1],
  [0, 40],
];
testpoint = points.map(([x,y]) => {
  return {x,y}
})
console.log(testpoint)
//0: {x: 4, y: 5}
//1: {x: 10, y: 1}
//2: {x: 0, y: 40}
```

# ES6でclass

```javascript
class Car {
  constructor(options) {  //初期化
    this.title = options.title;
  }
  drive(){  //メソッド
    return 'ウィーン'
  }
}

const car = new Car({title:'アクア'});
console.log(car);  //{title: "アクア"}
console.log(car.drive());  //ウィーン
```

## クラスの継承
```javascript
class Car {
  constructor(options) {
    this.title = options.title;
  }
  drive(){
    return 'ウィーン'
  }
}

class Toyota extends Car{  //Carクラスを継承する。
  constructor(options){
    super(options)  //Carのconstrutorを呼ぶ
    this.color=options.color
  }
  honk() {
    return 'ブブー'
  }
}

const toyota = new Toyota({color:'red', title:'アクア'});
console.log(toyota)          //{title: "アクア", color: "red"}
console.log(toyota.honk())   //ブブー
console.log(toyota.drive())  //ウィーン
```

# generator
## for...of ループ
for文で配列をループできる。そしてgeneratorと相性の良いループ機能

```javascript
const colors = ['red', 'green', 'blue'];
for(let color of colors) {
  console.log(color)  //red, green, blue
}
```

## generator入門
generatorでは関数の所で*を付ける。

```javascript
function* shopping() {
  console.log('歩道')
  console.log('歩道を歩いてお店にいく')
  console.log('お店に到着したのでお金をもってお店に入る')
  
  const stuffFromStore = yield 'お金';
  console.log('家に歩いて帰る')
  return stuffFromStore;
}
const gen= shopping();
console.log('家から歩道に出る')
console.log(gen.next());
console.log('日用品を持つ')
console.log(gen.next('日用品'));
console.log('お店で買い物をして日用品をもって歩道にでる。')

/**
 *上記コードの実行結果
 */
//家から歩道に出る
//歩道
//歩道を歩いてお店にいく
//お店に到着したのでお金をもってお店に入る
//{value: "お金", done: false}
//日用品を持つ
//家に歩いて帰る
//{value: "日用品", done: true}
//お店で買い物をして日用品をもって歩道にでる。
```
最初のgen.next()ではshopping関数のyieldまで処理が走り、抜ける。
次のgen.next('日用品')では続きのyieldから始まり、yieldの引数に'日用品'が入り、returnまで処理が続く。
これがgeneratorらしい。

done:false, done:trueについて

```javascript
function* colors(){
  yield 'red';
  yield 'blue';
  yield 'green';
}

const gen= colors()
console.log(gen.next())
console.log(gen.next())
console.log(gen.next())
console.log(gen.next())
/**
 *実行結果
 */
//{value: "red", done: false} 最初→redで止まり、false
//{value: "blue", done: false} red→blueで止まり、false
//{value: "green", done: false} blue→greenで止まり、false
//{value: undefined, done: true} green→最後まで行き、true
```

## jeneratorとfor...ofループを組み合わせる

``` javascript
const testingTeam = {
  lead: '典子',
  tester: '孝'
}

const engineeringTeam = {
  testingTeam,
  size:3,
  department:'開発部',
  lead:'太郎',
  manager:'花子',
  engineer:'次郎'
}

function* TeamIterator(team){
  yield team.lead;
  yield team.manager;
  yield team.engineer;
  const testingTeamGenerator = TestingTeamIterator(team.testingTeam);
  yield* testingTeamGenerator  //TestingTeamIteratorに飛ぶ
}

function* TestingTeamIterator(team){
  yield team.lead;
  yield team.tester;
}

const names = []
for (let name of TeamIterator(engineeringTeam)) {
  names.push(name)
}

console.log(names);
//["太郎", "花子", "次郎", "典子", "孝"]
```
## genetatorとsymbol.iterator
```javascript
const testingTeam = {
  lead: '典子',
  tester: '孝',
  //Symbol.iteratorを定義する
  [Symbol.iterator]: function* (){
    yield this.lead;
    yield this.tester;
  }
}

const engineeringTeam = {
  testingTeam,
  size:3,
  department:'開発部',
  lead:'太郎',
  manager:'花子',
  engineer:'次郎'
}

function* TeamIterator(team){
  yield team.lead;
  yield team.manager;
  yield team.engineer;
  yield* team.testingTeam;  //Symbol.iteratorがあるかどうかを見に行く
}

function* TestingTeamIterator(team){
  yield team.lead;
  yield team.tester;
}

const names = []
for (let name of TeamIterator(engineeringTeam)) {
  names.push(name)
}

console.log(names);
//["太郎", "花子", "次郎", "典子", "孝"]
```
リファクタ

```javascript
const testingTeam = {
  lead: '典子',
  tester: '孝',
  //Symbol.iteratorを定義する
  [Symbol.iterator]: function* (){
    yield this.lead;
    yield this.tester;
  }
}

const engineeringTeam = {
  testingTeam,
  size:3,
  department:'開発部',
  lead:'太郎',
  manager:'花子',
  engineer:'次郎',
  //Symbol.iteratorを定義する
  [Symbol.iterator]: function* (){
    yield this.lead;
    yield this.manager;
    yield this.engineer;
    yield* this.testingTeam;
  }
}

function* TestingTeamIterator(team){
  yield team.lead;
  yield team.tester;
}

const names = []
for (let name of engineeringTeam) {
  names.push(name)
}

console.log(names);
//["太郎", "花子", "次郎", "典子", "孝"]
```

## generatorと再起処理

```javascript
class Comment {
  constructor(content, children) {
    this.content = content;
    this.children = children;
  }
  *[Symbol.iterator]() {
    yield this.content;
    for (let child of this.children){
      yield* child;
    }
  }
}

const children = [
  new Comment('agree.',[]),
  new Comment('disagree',[]),
  new Comment('oom',[]),
]
const tree = new Comment('非常に良い記事です', children);
const values= [];
for (let value of tree) {
  values.push(value);
}

console.log(values)  //["非常に良い記事です", "agree.", "disagree", "oom"]
```

# promiseとfetch
## fetchでajax

```javascript
url = "https://jsonplaceholder.typicode.com/posts/";
fetch(url)
  .then(response => console.log(response.json()))
  .then(data=>console.log(data));    //jsonの値が入る。
```