JavaScript 応用編 (モダンなJavaScriptの機能)

# この記事の内容について
　JavaScriptの基礎学習を終えたので、書籍「モダン JavaScriptの基本から始まる React実践の教科書」で学習しながら、理解したことをアウトプットしていこうと思います。
　私はまだエンジニア歴1年未満の初学者なので、間違い等があればご指摘いただけると幸いです。

# JavaScript 基礎編
* [ブラウザオブジェクト / DOM](https://qiita.com/Nao52/items/c6b7531b85a5e4a6c8dc)
* [イベント](https://qiita.com/Nao52/items/6705eeca68a77b3f280a)
* [通信と非同期処理](https://qiita.com/Nao52/items/3ae127867cee0f838643)
* [ミニアプリの開発](https://qiita.com/Nao52/items/ed9f64a9b1c1da91abc0)

# JavaScript 応用編
* [モダンなJavaScriptの機能](https://qiita.com/Nao52/items/5ee9c2af96b4e9dfd278)

# 1. const / letでの変数宣言
### varでの変数宣言の問題点
* 上書き可能なこと
* 再宣言が可能なこと
```javascript:varを使った変数宣言
var name = "一郎";
console.log(`彼の名前は${name}です`); 
// 出力結果：彼の名前は一郎です

// var変数は上書き可能('一郎'を上書きできてしまう)
name = "二郎"
console.log(`彼の名前は${name}です`);
// 出力結果：彼の名前は二郎です

// var変数は再宣言が可能(nameを宣言できる)
var name = "三郎";
console.log(`彼の名前は${name}です`);
// 出力結果：彼の名前は三郎です
```

### letによる変数宣言
* 再宣言は不可能
* 上書きは可能

```javascript:letを使った変数宣言
let name = "一郎";
console.log(`彼の名前は${name}です`); 
// 出力結果：彼の名前は一郎です

// let変数は上書き可能
name = "二郎"
console.log(`彼の名前は${name}です`);
// 出力結果：彼の名前は二郎です

// nameは既に宣言されているため、エラーになる
let name = "三郎";
console.log(`彼の名前は${name}です`);
```

### constでの変数宣言
* 再宣言は不可能
* 上書きは不可能

```javascript:constを使った変数宣言
const name = "一郎";
console.log(`彼の名前は${name}です`); 
// 出力結果：彼の名前は一郎です

// エラーが発生
name = "二郎"
console.log(`彼の名前は${name}です`);

// エラーが発生
// let name = "三郎";
console.log(`彼の名前は${name}です`);
```

### constで宣言した変数の注意点
**オブジェクト型**のものはconstで定義しても中の値を変更できる

```javascript:オブジェクトの変更、追加
// オブジェクトの定義
const Takeshi = {
  name: "たけし",
  age: 24,
}
console.log(Takeshi);
// 出力結果：{name: 'たけし', age 24}

// プロパティ値の変更
Takeshi.age = 28;
console.log(Takeshi);
// 出力結果：{name: 'たけし', age 28}

// プロパティ値の追加
Takeshi.hobby = "野球";
console.log(Takeshi);
// 出力結果：{name: 'たけし', age 24, hobby: '野球'}
```

```javascript:配列の変更、追加
// 配列の定義
const fruits = ["apple", "banana", "grape"];
console.log(fruits);
// 出力結果：(3) ['apple', 'banana', 'grape']

// 3つ目の値を変更
fruits[2] = "orange";
console.log(fruits);
// 出力結果：(3) ['apple', 'banana', 'orange']

// 値を追加
fruits.push("strawberry");
console.log(fruits);
// 出力結果：(4) ['apple', 'banana', 'grape', 'strawberry']
```

# 2. テンプレート文字列
```javascript:テンプレート文字列の利用
// オブジェクトの定義
const mitsuki = {
  name: "高畑充希",
  ocupation: "女優",
}
// 下記の2つを出力すると結果は同じになる
console.log("彼女の名前は" + mitsuki.name + "です。職業は" + mitsuki.ocupation + "です");
console.log(`彼女の名前は${mitsuki.name}です。職業は${mitsuki.ocupation}です`);
// 出力結果：彼女の名前は高畑充希です。職業は女優です。

// シングルクオートとダブルクオートは使用できない。
console.log("彼女の名前は${mitsuki.name}です。職業は${mitsuki.ocupation}です");
console.log('彼女の名前は${mitsuki.name}です。職業は${mitsuki.ocupation}です');
// 出力結果：彼女の名前は${mitsuki.name}です。職業は${mitsuki.ocupation}です。
```

# 3. アロー関数　() => {}
### 従来の関数
```javascript:従来の関数の使い方
// 関数を定義
function hello(name) {
  return `こんにちは${name}さん`;
}
console.log(hello("山田"));
// 出力結果：こんにちは山田さん

// 関数を定義して、変数に格納
const greeting = function(name) {
  return `こんにちは${name}さん`;
}
console.log(greeting("山田"));
// 出力結果：こんにちは山田さん
```

### アロー関数
```javascript:アロー関数の書き方
// 関数を定義して、変数に格納
const greeting = (name) => {
  return `こんにちは${name}さん`;
}
console.log(greeting("山田"));
// 出力結果：こんにちは山田さん
```

### アロー関数の省略
```javascript:引数が1つのとき
// 引数が1つのとき、()が省略できる！
const greeting = name => {
  return `こんにちは${name}さん`;
}
console.log(greeting("山田"));
// 出力結果：こんにちは山田さん
```

```javascript:戻り値が1行のとき
// 戻り値が1行のとき、{}とreturnが省略できる！
const sum = (num1, num2) => num1 +  num2;
console.log(sum(10, 15));
// 出力結果：25
```

```javascript:()を使って、1行にまとめる
// ()を用いて、1行としてまとめる
const Anya = (name, age) => (
  {
    name: name,
    age: age,
  }
)
console.log(Anya("アーニャ", 6));
// 出力結果：{name: アーニャ, age 6}
```

# 4. 分割代入 {} []
```javascript:分割代入を使用しないで文字列を出力
const Anya = {
  name: "アーニャ",
  age: 6,
}
const greeting = `私の名前は${Anya.name}です。年齢は${Anya.age}歳です。`;
console.log(greeting);
// 出力結果：私の名前はアーニャです。年齢は6歳です。
```

```javascript:オブジェクトの分割代入
const Anya = {
  name: "アーニャ",
  age: 6,
}
// オブジェクトの分割代入
const {name, age} = Anya;
const greeting = `私の名前は${name}です。年齢は${age}歳です。`;
console.log(greeting);
// 出力結果：私の名前はアーニャです。年齢は6歳です。
```

```javascript:配列の分割代入
const Anya = ["アーニャ", 6]
// 配列の分割代入
const [name, age] = Anya;
const greeting = `私の名前は${name}です。年齢は${age}歳です。`;
console.log(greeting);
// 出力結果：私の名前はアーニャです。年齢は6歳です。
```

※ 配列の分割代入は「**順番の入れ替えができない**」ので注意する。

# 5. デフォルト値 =
### 引数のデフォルト値
```javascript:デフォルト値を設定しない
const sayHello = name => `こんにちは、${name}さん`;
console.log(sayHello());
// 出力結果：こんにちはundifinedさん
```

```javascript:default値をゲストに設定
const sayHello = (name = "ゲスト") => `こんにちは、${name}さん`;
console.log(sayHello());
// 出力結果：こんにちはゲストさん
```

### オブジェクト分割代入のデフォルト値
```javascript:存在しないプロパティ値の入力
const Anya = {
  name: "アーニャ",
  age: 6,
}
const {food} = Anya;
const message = `好きな食べ物は${food}です`;
console.log(message);
// 出力結果：好きな食べ物はundifinedです
```

```javascript:分割代入時にデフォルト値を設定
const Anya = {
  name: "アーニャ",
  age: 6,
}
const {food = "ピーナツ"} = Anya;
const message = `好きな食べ物は${food}です`;
console.log(message);
// 出力結果：好きな食べ物はピーナツです
```

# 6. スプレッド構文 ...
### 要素の展開
```javascript:配列の展開
const array = [10, 20, 40, 80];
console.log(array);
// 出力結果：(4) [10, 20, 40, 80]
console.log(...array);
// 出力結果： 10 20 40 80

// 引数を合計するsum()を定義
const sum = (num1, num2, num3, num4) => console.log(num1 + num2 + num3 + num4);
sum(array[0], array[1], array[2], array[3]);
sum(...array);
// 出力結果 150
```

### 要素をまとめる
```javascript:要素をまとめる
const array = [10, 20, 40, 80];

// 分割代入時に残りをまとめる
const [num1, ...array2] = array;

console.log(array);
// 出力結果：(4) [10, 20, 40, 80]
console.log(num1);
// 出力結果：10
console.log(array2);
// 出力結果：(3) [20, 40, 80]
```

### 要素のコピー、結合
```javascript:配列のコピー、結合
const color1 = ["red", "blue", "yellow"];
const color2 = ["white", "black"];

// color1をコピー
const color3 = [...color1];
// color1とcolor2を結合
const color4 = [...color1, ...color2];

console.log(color1);
// 出力結果：(3) ['red', 'blue', 'yellow']
console.log(color2);
// 出力結果：(2) ['white', 'black']
console.log(color3);
// 出力結果：(3) ['red', 'blue', 'yellow']
console.log(color4);
// 出力結果：(5) ['red', 'blue', 'yellow', 'white', 'black']
```

```javascript:オブジェクトのコピー、結合
// オブジェクトを2つ定義
const test1 = {
  japanese: 60,
  math: 70,
  english: 90,
}
const test2 = {
  society: 60,
  science: 70,
}

// test1のコピー
const test3 = {...test1};
// test1とtest2の結合
const test4 = {...test1, ...test2};

console.log(test1);
// 出力結果：{japanese: 60, math: 70, english: 90}
console.log(test2);
// 出力結果：{society: 60, science: 70}
console.log(test3);
// 出力結果：{japanese: 60, math: 70, english: 90}
console.log(test4);
// 出力結果：{japanese: 60, math: 70, english: 90, society: 60, science: 70}
```

### イコール(=)でのコピーとの違い
##### スプレッド構文でのコピー 
新しい配列やオブジェクトを生成して、コピーを行う
※ コピー先を変更しても、コピー元は**変わらない**
##### イコールでのコピー
参照先をコピーしてしまう
※ コピー先を変更すると、コピー元も**変化する**

# 7. オブジェクトの省略記法
### プロパティ名と変数名が同一の場合は省略できる！
```javascript:プロパティ名と変数名が同一
const name = "アーニャ";
const age = 6;

// 省略しないとき
const user1 = {
  name: name,
  age: age,
};
console.log(user1);
// 出力結果：{name: アーニャ, age: 6}

// 省略記法
const user2 = {
  name,
  age,
};
console.log(user2);
// 出力結果：{name: アーニャ, age: 6}
```

# 8. map / filter
### 従来のfor文
```javascript:for文での配列処理
const names = ["桜木", "流川", "赤木"];

for (let index = 0; index < names.length; index++) {
  console.log(names[index]);
}
```

### map関数
```javascript:map関数の使用例
const names = ["桜木", "流川", "赤木"];

names.map( name => console.log(name) );
// 出力結果：
// 桜木
// 流川
// 赤木
```

### filter関数
```javascript:filter関数の使用例
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

// 4以上の数字を抽出
const bigNums = numbers.filter( num => num >= 4 );
console.log(bigNums);
// 出力結果：(4) [4, 5, 6, 7, 8, 9, 10]
```

### indexの扱い
```javascript:for文でのindexの使用
const names = ["桜木", "流川", "赤木"];

for (let index = 0; index < names.length; index++) {
  console.log(`${index + 1}番目は${names[index]}です`);
}
// 出力結果：
// 1番目は桜木です
// 2番目は流川です
// 3番目は赤木です
```

```javascript:map関数でのindexの使用
const names = ["桜木", "流川", "赤木"];

names.map( (name, index) => console.log(`${index + 1}番目は${names[index]}です`) );
// 出力結果：
// 1番目は桜木です
// 2番目は流川です
// 3番目は赤木です
```

# 9. 三項演算子
```javascript:三項演算子の使用例
const user1 = {
  name: "kenji",
  gender: 1,
}
const user2 = {
  name: "erika",
  gender: 2,
}

const checkGender = gender => {
  return gender === 1 ? "男性" : "女性";
}
console.log(checkGender(user1.gender));
// 出力結果：男性
console.log(checkGender(user2.gender));
// 出力結果：女性
```