ES2015っぽいjsのメモ

# この記事は…

個人的な勉強のメモとして書いたものです、正確性などは保証しません

## const, let

### let

#### 変数の重複を許可しない

```js
let msg;
let msg = 'hoge'; // error
```

#### ブロックスコープを意識する

今まで

```js
if(hoge) {
  var i = 5;
}

console.log(i); // => 5
```

これから

```js
if(hoge) {
  let i = 5;
}

console.log(i); // => undefined
```

ES2015ではブロックスコープが使えるので

```js
{
  let i = 5;
}

console.log(i); // => undefined
```

Switchでは注意が必要

```js
switch(x) {
  case 0:
    let value = 'x:0'; // ここでvalueを宣言
  case 1;
    let value = 'x:1'; // => スコープはないのでここでエラー
}
```

### const

再代入を許さない

```js
const i = 1;
i = 10; // => error
```

## class

### class命令による指定

```js
class Double {
  // コンストラクタ
  constructor(a, b) {
    this.a = a;
    this.b = b;
  }
  
  // メソッド
  getSum() {
    return this.a + this.b;
  }
}
```

### class式による定義

```js
const Double = class {
  constructor(a, b) {
    this.a = a;
    this.b = b;
  }
  
  getSum() {
    return this.a + this.b;
  }
}
```

### 注意

#### 宣言した後のみに使える

巻き上げはできない、必ず宣言してから出ないとエラーになる

```js
const hoge = new Double(); // => error
class Double { ... };
```

#### class内はstrictモードで実行される

#### constructor命令は二回以上できない


### プロトタイプメソッド `==` プロパティ

get, setが使える

```js
class Double {
  constructor(a, b) {
    this.a = a;
    this.b = b;
  }

  get c() {
    return this.c ? this.c : 0;
  }
  
  set c(value) {
    this.c = value;
  }
    
  getSum() {
    return this.a + this.b + this.c;
  }
}
```

### 静的メソッド

インスタンス化されない。ユーティリティメソッドを作るときによく使う。

```js
class Double {
  constructor(a, b) {
    this.a = a;
    this.b = b;
  }
  
  static distance(a, b) {
    return Math.abs(a = b);
  }
  
  getArea() {
    return Math.pow(distance(this.a, this.b));
  }
}

const hoge = new Double(2, 4);
hoge.getArea();  // 4
hoge.distance(2, 4); // => インスタンス化して呼び出すとerror

Double.distance(2, 4); // => 2
```

### 継承

```js
class Double {
  constructor(a, b) {
    this.a = a;
    this.b = b;
  }
  
  getArea() {
    return this.a * this.b;
  }
}

class DoubleAddGridMethod extends Double {
  getGrid() {
    return this.a;
  }
}
```

### superキーワード
constructorやメソッドに何か上書きしたいときに親クラスの変数や関数を呼び出す


```js
class Double {
  constructor(a, b) {
    this.a = a;
    this.b = b;
  }
  getArea() {
    return this.a * this.b;
  }
}

class DoubleAddProperty extends Double {
  constructor(a, b, c) {
    super(a, b);  // a, b を親クラスを上書き
    this.c = c;
  }
  getArea() {
    return super.getArea() * this.c;
  }
}
```

### classのexport, import

```file-a.js
class Double {
  constructor(a, b) {
    this.a = a;
    this.b = b;
  }
  getArea() {
    return this.a * this.b;
  }
}
```

#### impoprtの仕方1

```file-b.js
import * from "./file-a.js";
const d = new Double(3, 4);
```

#### impoprtの仕方2

```file-b.js
import Double from "./file-a.js";
const d = new Double(3, 4);

// これだとfile-a.jsで複数のclassを指定していてもDoubleだけが呼び出される
// 複数を呼び出したい場合は import { Double1, Double2 } from "./file-a.js"; のように読む
// すべて呼び出したい場合は * を使う
```

#### impoprtの仕方3

```file-b.js
import { HogeDouble as Double } from "./file-a.js";
const d = new HogeDouble(2, 3);
```

## Arrow Function

[アロー関数 - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/arrow_functions)

Arrow Functionは常に匿名関数

### 基本

```js
(param1, param2, ... , paramN) => { // 処理 }

// returnのみのときは{}を省略できる
(param1, param2, ... , paramN) => { return hoge }
(param1, param2, ... , paramN) =>  hoge


// paramが一つのときは()を省略できる
param => { statement };

// paramが0つのときは()は省略できない
() => { statement }
```

### 応用

```js
// objectリテラルを返すときは()で囲む
(param1, ... , paramN) => ({name: "takashi", age: 23});

// 残りの引数(...hoge), デフォルト引数がサポート
(params1 = defaultValue1, ...rest) => { // 処理 };

// 分割代入
var f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c;
f(); // => 6
```

## Promiseコンストラクタと thenメソッド

### Promise, thenの基本


```js
let asyncProcess = (value) => {
  // Promiseは resolve: 処理の成功を通知する関数とreject: 処理の失敗を通知する関数で
  return new Promise((resolve, reject) => {  
    setTimeout(() => {
   　　{value
   　　  && resolve(value)
   　　  || reject("入力が空")
  　 　}
    }, 5000);
  });
}  

// 関数を実行してみる
// Promise.then(sucsess: function, resoluveで呼び出される, failure: function, rejectで呼び出される
asyncProcess('hoge').then(
  responce => {
    console.log(responce);
  },
  error => {
    console.log(error);
  }
});

```

### Promiseの連結

```js
asyncProcess('hoge').then(
    response => {
      console.log(response);
      return asyncProcess('hoge');
    }
)
.then(
    response => {
      console.log(response);
    }
);
```

一回読んで、その後またthenで呼び続けられる. Promiseを返す必要がある


### すべての非同期処理が成功した場合にコールバック => Promise.all(関数の配列)
配列で入れる

```js
Promise.all([
  asyncProcess('hoge'),
  asyncProcess('foo'),
  asyncProcess('bar')
]).then(
  response => {
  	console.log(response);
  },
  error => {
    console.log(error);
  }
);
```

### 一つが完了したらコールバックする => Promise.race

```js
Promise.race([
  asyncProcess('hoge'),
  asyncProcess('foo'),
  asyncProcess('bar')
]).then(
  response => {
  	console.log(response);
  },
  error => {
    console.log(error);
  }
);
```

## 文字列処理

ES2015じゃないけどよく使うのはこの辺

- https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/slice
- https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/replace
- https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/match
- https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/split
- https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/parseInt

## オブジェクト

### 変更点1: オブジェクト内でもthisが使えるようになった

```js
let Area = {
  a: 1;
  b: 2;
  getArea(): {
    return this.a * this.b;  // ここでthisが使えるようになった
  }
}
```

### 変更点2: もう名前割り当ててたら省略できる

```js
let name = "takashi";
let family = "kita";
let truename = { family, name };
```

### 変更点3: プロパティの動的生成

```js
let i = 0;
let office = {
  name: "takashi-social-company",
  birth: new Date(2008, 2, 26),
  ['memo' + ++i]: "memo",
  ['memo' + ++i]: "memomemo"
}
```