JavaScript初心者が最低限これだけは覚えておくこと

## 概要
JavaScriptを勉強し始めたので自身の備忘録のために分かりやすく自分の言葉で噛み砕いて解説して残しておく

## 目次
[1. 変数](#1-変数)
&emsp;[1-1. const](#1-1-const)
&emsp;[1-2. let](#1-2-let)
[2. テンプレート文字列](#2-テンプレート文字列)
[3. アロー関数](#3-アロー関数)
[4. 分割代入](#4-分割代入)
&emsp;[4-1. 配列の分割代入](#4-1-配列の分割代入)
&emsp;[4-2. オブジェクトの分割代入](#4-2-オブジェクトの分割代入)
[5. デフォルト引数](#5-デフォルト引数)
[6. オブジェクトの省略記法](#6-オブジェクトの省略記法)
&emsp;[6-1. プロパティ名の省略](#6-1-プロパティ名の省略)
&emsp;[6-2. 関数プロパティの省略](#6-2-関数プロパティの省略)
[7. スプレッド構文](#7-スプレッド構文)
[8. forEach/map/filterを使った処理](#8-foreach/map/filterを使った処理)
&emsp;[8-1. forEachメソッド](#8-1-foreachメソッド)
&emsp;[8-2. mapメソッド](#8-2-mapメソッド)
&emsp;[8-3. filterメソッド](#8-3-filterメソッド)
&emsp;[8-4. forEachとmapの違い](#8-4-foreachとmapの違い)
&emsp;[8-5. mapとfilterの違い](#8-5-mapとfilterの違い)
[9. 三項演算子](#9-三項演算子)
[10. truthyとfalsy](#10-truthyとfalsy)


## 1. 変数
### 1-1. const
再代入が出来ない変数の宣言。
```js:例
const name = '田中';
```

```js
const name = '田中';
name = '佐藤';  // エラーになる(Uncaught TypeError: Assignment to constant variable)
```

### 1-2. let
再代入が出来る変数の宣言。
```js:例
let name = '田中';
name = '佐藤';

console.log(name);  // 佐藤
```

## 2. テンプレート文字列
文字列の結合のこと。
使い方は文字列をバッククォート 「`」で囲み、jsの文は${変数名}で囲む。
```js:例
const name = '田中';
const age = 30;
const message = `私の名前は${name}です。年齢は${age}歳です。`;

console.log(message);  // 私の名前は田中です。年齢は30歳です。
```

## 3. アロー関数
従来はfunctionを用いた関数が、ES6から別の書き方が可能になった。
=> が弓矢にみえることからアロー関数と呼ぶ。

```js:例：従来のfunctionを用いた場合
function sum(num){
  return num + 1;
}

console.log(sum(2));  // 3
```

```js:関数定義
定数 or 変数名 = (引数) => { 処理 };
```

```js:例：引数が一つの場合
const func = (num) => {
  return num + 1;
};

console.log(func(2));  // 3
```

```js:例：引数が複数の場合
const func = (num1, num2) => {
  return num1 + num2;
};

console.log(func(10, 20));  // 30
```

```js:例：オブジェクトで返す場合
const func = (num1, num2) => ({
  hoge1: num1,
  hoge2: num2,
  total: num1 + num2,
});

console.log(func(2, 3)); // {hoge1: 2, hoge2: 3, total: 5} 
```

ちなみに引数が一つの場合、（）を省略できる。
引数が無い場合は（）を省略してはいけない。（エラーになる）
```js
const func = num => {
  return num + 1;
};

console.log(func(2));  // 3
```

## 4. 分割代入
配列/オブジェクトから値/プロパティを取り出して別個の変数に代入すること。

### 4-1. 配列の分割代入
```js:例：分割代入しない場合
const myProfile = ['田中', 30];
const message = `私の名前は${myProfile[0]}です。年齢は${myProfile[1]}歳です。`;

console.log(message); // 私の名前は田中です。年齢は30歳です。
```

```js:例：分割代入した場合
const myProfile = ['田中', 30];
const [name, age] = myProfile;
// 分割で値を取り出した場合、myProfile[x]が不要になる
const message = `私の名前は${name}です。年齢は${age}歳です。`;

console.log(message); // 私の名前は田中です。年齢は30歳です。
```

### 4-2. オブジェクトの分割代入
```js:例：分割代入しない場合
const myProfile = {
  name: '田中',
  age: 30,
};
const message = `私の名前は${myProfile.name}です。年齢は${myProfile.age}歳です。`;
console.log(message); // 私の名前は田中です。年齢は30歳です。
```

```js:例：分割代入した場合
const myProfile = {
  name: '田中',
  age: 30,
};
const { name, age } = myProfile;
// 分割で値を取り出した場合、myProfile.xxxが不要になる
const message = `私の名前は${name}です。年齢は${age}歳です。`;

console.log(message); // 私の名前は田中です。年齢は30歳です。
```

## 5. デフォルト引数
関数に値が渡されない場合や`undefined`が渡された場合に、デフォルト値で初期化される形式上の引数を指定することが可能。

```js:例
const myProfile = {
  age: 55,
};
const { name = 'デフォルト', age } = myProfile;

console.log(name, age); // デフォルト 55
```

```js:例
const myProfile = (name = 'デフォルト') => {
  return name;
};

console.log(myProfile()); // デフォルト
```

```js:例
const myProfile = (name = 'デフォルト', age) => {
  return [name, age];
};

console.log(myProfile('田中', 30)); // ['田中', 30]
```

### 注意点
一つ目にデフォルト引数を設定し、二つ目にデフォルト値が存在しない引数を設定すると、デフォルト引数の値が上書きされてしまうので注意が必要。
```js:例：NG
const myProfile = (name = 'デフォルト', age) => {
  return [name, age];
};

console.log(myProfile(30)); // [30, undefined]
```

初期値が指定されている引数の位置が分かっているのであれば、その引数にundefinedが当たるようにすれば良い。
```js:例：OK
const myProfile = (name = 'デフォルト', age) => {
  return [name, age];
};

console.log(myProfile(undefined, 30)); // ['デフォルト', 30]
```

## 6. オブジェクトの省略記法
### 6-1. プロパティ名の省略
オブジェクトの`キー名`と`値の変数名`が一致する場合、省略して書くことが可能。

```js:例：省略記法を用いていない場合
const name = "田中"
const age = 30;
const myProfile = {
  name:name,
  age:age
};

console.log(myProfile); // {name: '田中', age: 30}
```

```js:例：省略記法を用いた場合
const name = '田中';
const age = 30;
const myProfile = {
  name,
  age,
};

console.log(myProfile); // {name: '田中', age: 30}
```

### 6-2. 関数プロパティの省略
オブジェクトのプロパティに関数を設定する場合も省略が可能。
```js:例：省略記法を用いていない場合
const message = {
  greeting(name) {
    return `こんにちは${name}さん`;
  },
};

console.log(message.greeting('田中')); // こんにちは田中さん
```

`:function`を省略出来る
```js:例：省略記法を用いた場合
const message = {
  greeting:function (name) {
    return `こんにちは${name}さん`;
  }
};

console.log(message.greeting('田中')); // こんにちは田中さん
```

## 7. スプレッド構文
`...`を配列やオブジェクトの前に記載することにより、使用可能。
配列やオブジェクトなどを展開することが可能となる。

```js:例：配列をまとめる①
const arr1 = [1, 2, 3, 4, 5, 6];
const [...arr2] = arr1;

console.log('arr2', arr2); // [1, 2, 3, 4, 5, 6]
```

```js:例：配列をまとめる②
const arr1 = [1, 2, 3, 4, 5, 6];
const [num1, num2, num3, ...arr2] = arr1;

console.log('num1', num1); // 1
console.log('num2', num2); // 2
console.log('num3', num3); // 3
console.log('arr2', arr2); // [4, 5, 6]
```

```js:例：配列のコピー
const arr1 = [1, 2];
const arr2 = [3, 4];
const arr3 = [...arr2];

console.log('arr3', arr3); // [3, 4]
```

```js:例：配列の結合
const arr1 = [1, 2];
const arr2 = [3, 4];
const arr3 = [...arr1, ...arr2];

console.log('arr3', arr3); // [1, 2, 3, 4]
```

## 8. forEach / map / filter を使った処理
### 8-1. forEachメソッド
繰り返し処理を行うために使われるメソッド。
配列のすべての要素に対してコールバック関数の処理を行う。
単純に処理を実行するのみのため、返り値は無い。<font color="Red">returnを記述すると、undefinedが返る</font>。

### 8-2. mapメソッド
繰り返し処理を行い、新しい配列を作るメソッド。
forEachメソッドと同様、配列のすべての要素に対してコールバック関数の処理を行う。
実行結果が配列データとして返る。そのため、returnを記述することが出来る。

### 8-3. filterメソッド
条件に一致する要素を検索し、新しい配列を作るメソッド。
mapメソッドと同様に、与えられたコールバック関数の処理を行い、新しい配列を生成するため、返り値を持つことが出来る。
条件に一致した要素のみを返すという点が特徴。

:::note info
**ポイント**
* forEachメソッドは、すべての配列要素に対して処理を行い、その結果を取得する
* mapメソッドは、すべての配列要素に対して処理を行い、その結果を配列として返す
* filterメソッドは、条件に一致した配列要素をフィルタリングし、その要素のみの配列を返す
:::

### 8-4. forEachとmapの違い
```js:例
const arr = [1, 2, 3, 4, 5];

// forEachの場合
arr.forEach((value) => {
  console.log(value * 2);
});
// 2
// 4
// 6
// 8
// 10

// mapの場合
arr.map((value) => {
  console.log(value * 2);
});
// 2
// 4
// 6
// 8
// 10
```

forEachもmapも得られる結果は同じ。
<font color="Red">大きく異なる点は、戻り値を持つかどうか。</font>
今度は戻り値を記述して比較してみる。

```js:例
const arr = [1, 2, 3, 4, 5];

// forEachの場合
const forEachResult = arr.forEach((value) => {
  return value * 2;
});
console.log(forEachResult); // undefined

// mapの場合
const mapResult = arr.map((value) => {
  return value * 2;
});
console.log(mapResult); // [2, 4, 6, 8, 10]
```

forEachはundefinedとなり、mapでは[2, 4, 6, 8, 10]という結果になった。
つまり、forEachは要素に対して単に処理を実行するメソッドである一方、mapは戻り値として配列データを取得するメソッドになる。

### 8-5. mapとfilterの違い
```js:例：
const arr = [10, 20, 30, 40, 50];

// mapの場合
const mapResult = arr.map(value => {
  return value / 2;
});
console.log(mapResult); //[5, 10, 15, 20, 25]

// filterの場合
const filterResult = arr.filter(value => {
  return value / 2;
});
console.log(filterResult); //[10, 20, 30, 40, 50]
```
mapは要素を2で割った値を配列で返しているのに対して、filterは要素の中から2で割れる要素のみを配列で返している。
filterは、配列要素のうち条件にあった要素のみをフィルタリングし、それを配列として返しているということ。

```js:例
const arr = [3, 13, 27, 30, 33];

// mapの場合
const mapResult = arr.map(value => {
  return value % 3;
});
console.log(mapResult); // [0, 1, 0, 0, 0]

// arr配列が [3, 13, 27, 30, 33] の場合、それぞれの要素に対する余りは以下のように計算
// 3 % 3 = 0
// 13 % 3 = 1
// 27 % 3 = 0
// 30 % 3 = 0
// 33 % 3 = 0

// filterの場合
const filterResult = arr.filter(value => {
  return value % 3;
});
console.log(filterResult); // [13]

// arr配列が [3, 13, 27, 30, 33] の場合、それぞれの要素に対する余りは以下のように計算
// 3 % 3 = 0 （0はfalseと評価される）
// 13 % 3 = 1 （1はtrueと評価される）
// 27 % 3 = 0 （0はfalseと評価される）
// 30 % 3 = 0 （0はfalseと評価される）
// 33 % 3 = 0 （0はfalseと評価される）
```
mapは、配列要素すべてに除算する関数を実行し、その計算結果を新しい配列で返している。
filterは、配列要素の中で除算できる要素を探し、フィルタリングされた要素のみを配列で返している。
<font color="Red">mapは区別せずにすべての要素を返すのに対し、filterは条件内容によって要素を区別することが大きな違い。</font>
filterの実行結果では、条件に当てはまらない要素は省かれるため、元の要素の数よりも少なくなる場合がある。

## 9. 三項演算子
```js:構文
条件式 ? trueの時の式 : falseの時の式
```

```js:三項演算子を使わない場合
let point = 60;
let msg;
if (point > 70) {
  msg = '合格';
} else {
  msg = '不合格';
}

console.log(msg); // 不合格
```

```js:例
let point;
point = 80;
let msg = point > 70 ? '合格' : '不合格';

console.log(msg); // 合格
```

```js:例
let point;
point = 50;
let msg = point > 70 ? '合格' : '不合格';

console.log(msg); // 不合格
```

## 10. truthyとfalsy
:::note info
* truthy：Booleanで真偽値に変換した場合にtrueになる値のこと
* falsy：Booleanで真偽値に変換した場合にfalseになる値のこと
:::

truthyとfalsyの見分け方は、基本的にfalsyのものを覚えて、falsy以外のものは全てtruthyだと判断すると良い。

### ↓ falsyの図
| 値 |型|  
|:-----------|:------------|
| false       | boolean| 
| 0(数字)       | number        | 
| -0(数字)       | number        | 
| 0n      | bigint        | 
| ""(空文字列)       | string        | 
| null       | null        | 
| undefined       | undefined        | 
| NaN(Not A Number)      | number        | 

<font color="Red">上記の図で表記されていない値はtruthyとなる</font>

### 注意点
オブジェクト{}や[]といった空のものは、trueとなる
```js
const arr = [];
const result = arr ? 'true' : 'false';

console.log(result); // ture
```