【JS/ES6】ES6のよく使うタグの備忘録メモ


# はじめに
ES6を勉強する中でよく使うタグの備忘録メモ。

## varとletとconstの使い分け
### varとletは参照できるスコープが違う
varとletはどちらも定義した後に変更できる変数だが、参照できるスコープが違う。

- var : 関数内のどこからでも参照ができる
- let : ブロック内のみしか参照できない

#### varの場合
``` js
const varScope = (scope) => {
    if(scope == "var"){
        var message = "hoge"
    }
    console.log(message); // hoge
}
```

#### letの場合
``` js
const letScope = (scope) => {
    if(scope == "var"){
        let message = "hoge"
    }
    console.log(message); // error
}
```

### なぜスコープが狭くなったのか？
元々ES6以前は変数はvarしかなかった。
ES6に追加されたletはスコープをブロック内に制限することで、ブロック単位で変数を管理できて想定外のバグが起きにくくなるメリットがある。

### constは再定義不可だが配列やオブジェクトはOK！
変数（varとletとconst）には宣言後に変更可能な「mutable」と変更不可な「immutable」があり、varとletはmutableで、constはimmutable。

constはimmutableなので、基本的に定義後に変更しない定数などを格納する。
ただ、配列やオブジェクトなどはconstで定義しても後から変更（追加や削除含む）が可能。

``` js
const hoge = "hoge";
hoge = "fuga"; // error
```

``` js
const hogeAry = [0,1,2];
hogeAry.push(3); //OK
console.log(hogeAry); // [0,1,2,3]
```

## 関数はモジュール化する
関数はモジュール化して必要なJSで読みこんで使う！
``` js/modules/hamburger.js
const hamburger = () => {
  /* 省略 */
};

export default hamburger;
```
``` js/main.js
import hamburger from './modules/hamburger';

window.addEventListener('load', () => {
  hamburger();
});
```

## アロー関数
もうこれじゃない
``` js
function hoge(){
~~
}
```
アロー関数は=>で関数をつなげて書く！
``` js
const hoge = (引数) => {
~~~
}
```
もしくは1行で書ける処理は下記のように書ける。
```
const hoge = (引数) => return 引数;
```

## DOM取得系

### IDを指定して取得する
``` js
document.getElementById('hoge');
```
### CLASSを指定して取得する
``` js
const classes = document.getElementByClassName('hoge');

for(item of classes){
    console.log(item);
}
```
- getElementByClassNameでは指定したclassがついたDOMをすべて取得するので、forで取り出す必要がある

### data属性を指定して取得する
``` js
<header class="header" data-selector="header"></header>

const header = document.querySelector('[data-selector=header]');
```

### その他の取得系まとめ

#### name属性で要素を取得
``` js
document.getElementsByName(name)
```
#### タグ名で要素を取得
``` js
document.getElementsByTagName(name)
```

#### セレクターで要素(最初の1つ)を取得
``` js
document.querySelector(selectors)
```

#### セレクターで要素(複数)を取得
``` js
document.querySelectorAll(selectors)
```

#### 親要素を取得
``` js
document.querySelectorAll(selectors)
```


### form

``` js
<form name="hogeForm">
    <input name="title">
</form>

const form = document.forms.hogeForm;
const title = form.title.value;
console.log(title);
```
- まずはform自体を取得して、formの中にあるinputたちをnameを指定して取得する。

## 配列系
### map(新しい配列を作る）
``` js
const hogeArry = [0,1,2];
const newArry = hogeArry.map(index, index + 1);
console.log(newArry); // [1,2,3];
```
既存オブジェクトからキー(ユーザー名)を取得し、新しいオブジェクトにユーザー名を追加して新しくオブジェクトを作成する。
``` js
const obj = {
 "user1": {"name":"hoge"},
 "user2": {"name":"fuga"},
 "user3": {"name":"takegons"},
}

const newObj = Object.keys(obj).map(key => {
// ↑Object.keys()は指定したオブジェクトをキーの配列にする（それをmapで回す）
const val = obj[key] // 配列なので[key]で中身を取得
newVal['username'] = val;
return newVal;
})

console.log(newObj);
// {"username": "user1", "name":"hoge"}
// {"username": "user2", "name":"fuga"}
// {"username": "user3", "name":"takegons"}

```

### filter（特定のデータを取得する）
``` js
const obj = {
    {"username": "user1", "name":"hoge"},
    {"username": "user2", "name":"fuga"},
    {"username": "user3", "name":"takegons"}
}

const resultObj = obj.filter(returnObject => {
    return returnObject.username === 'user3';
})

console.log(resultObj);
// {"username": "user3", "name":"takegons"}

```

### findIndex(特定の項目の順番を取得)
``` js
const obj = {
    {"username": "user1", "name":"hoge"},
    {"username": "user2", "name":"fuga"},
    {"username": "user3", "name":"takegons"}
}

const index = obj.findIndex(returnObject => {
    return returnObject.username === "user3";
})
console.log(index); // 2
console.log(obj[index]); // {"username": "user3", "name":"takegons"}
```

## class

### classの定義
``` js
class Student {
    avg(){
        console.log((80+70) / 2);
    }
}
```
### classの定義②
``` js
var Student = class {
    ~~
};
```

### classを使う
classはインスタンス化して使う。
``` js
class Student {

    avg(){
        console.log((80+70) / 2);
    }

}

let student1 = new Student; // インスタンス化
student1.avg();
```

### インスタンスにプロパティを追加する
プロパティはインスタンスごとに設定する必要がある。
``` js

class Student {

    avg(){
        console.log((80+70) / 2);
    }

}

let student1 = new Student; // インスタンス化
student1.avg();
student1.name = "takegons";
console.log(student1.name) // takegons
console.log(student1.age) // undefined ※プロパティを追加してないからエラーになる

let student2 = new Student; // インスタンス化
student2.age = 16;
console.log(student2.name) // undefined ※プロパティを追加してないからエラーになる
console.log(student2.age) // 16
```

上記のようにプロパティはインスタンスごとに定義する必要がある。
これがインスタンスが増えたらめんどうなのでコンストラクタを使う。

### コンストラクタ
コンストラクタはclassをインスタンス化したときに呼び出される初期化メソッド。
``` js
class Student {
    constructor(){
        this.name = ""; // ここで定義しておく
    }
    avg(){
        console.log((80+70) / 2);
    }
}
let student1 = new Student; // インスタンス化
student1.name = "takegons";
console.log(student1.name) // takegons

let student2 = new Student; // インスタンス化
console.log(student2.name) // ""
```

#### インスタンス化と一緒に引数で渡す
``` js
class Student {
    constructor(name, age){
        this.name = name;
        this.age = age;
    }
}
let student1 = new Student("takegons", 16); // インスタンス化
console.log(student1.name) // takegons
console.log(student1.age) // 16

let student2 = new Student("hogesan", 15); // インスタンス化
console.log(student2.name) // "hogesan"
```

### 実際のテストコード
- Systemクラスを定義する
- ユーザーごとにインスタンス化してテスト結果を渡す
- テスト結果の平均点を返すメソッドを作り実行する
``` js
class System {
    constructor(username){
        this.username = username;
    }

    avg_score(data){
        let sum = 0;
        for(let i = 0; i < data.length; i++){
            sum += data[i];
        }
        let avg = sum / data.length;
        return avg;
    }
}

let user1 = new System("takegons");
let data = [85, 60, 98, 90];
let avg = user1.avg(data);

console.log(avg);
```