JavaScriptの記法についての備忘録

# はじめに
お疲れ様です、りつです。

React学習を行うにあたり、JavaScriptの記法について把握しておくことは重要です。
今回は特にモダンJavaScriptの記法について、復習と備忘録も兼ねてまとめてみました。

:::note info
Reactの基礎を学ぶ上で、じゃけぇさんのUdemy動画には大変お世話になりました。
JavaScriptの記法についても丁寧に説明されておりますので、もっと詳しく知りたい方はぜひ視聴してみてください。
:::

https://www.udemy.com/course/modern_javascipt_react_beginner/?couponCode=BASIC20241001

※ なお、以下で載せている実行例や実行結果ですが、直前で実行したものと同一内容の場合は省略しております。

# 1. アロー関数

シンプルな関数をもとに、通常の書き方と、それをアロー関数ではどのように記述できるかをまとめます。

## 通常の関数の書き方

以下は、引数で受け取った名前をもとに、あいさつを返す関数です。
通常の記述方法は以下のようになります。

### 記法
```javascript
function sayHello(name) {
 return "こんにちは！" + name + "さん";
}
```

### 実行例
```javascript
console.log(sayHello('りつ'));
```

### 実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3911933/0ed47eea-54fe-64fe-0538-b60f1932837b.png)

## アロー関数の書き方

ここからは、「[通常の関数の書き方](#通常の関数の書き方)」で記載した関数を、アロー関数で表現してみます。

### アロー関数（省略なし）

```javascript
const sayHello = (name) => {
 return "こんにちは！" + name + "さん";
}
```

### アロー関数（引数の括弧の省略記法）

:::note info
POINT!
引数がひとつの場合は、引数を囲んでいる括弧を省略できます。
:::

```javascript
const sayHello = name => {
 return "こんにちは！" + name + "さん";
}
```

### アロー関数（単一式を返却する場合の省略記法）

#### 例1

:::note info
POINT!
単一式をreturnする場合、波括弧とreturnを省略できます。
:::

```javascript
const sayHello = (name) => 'こんにちは！' + name + 'さん';
```

#### 例2

:::note info
POINT!
オブジェクトなど複数行にまたがる式を返却したい場合は、式を`()`で囲むことにより返却できます。
:::

##### 記法
```javascript
const getNameObj = (firstName, lastName) => ({
  firstName: firstName,
  lastName: lastName,
});
```

##### 実行例
```javascript
console.log(getNameObj('太郎', '田中'));
```

##### 実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3911933/6cd96c9e-b1c3-e0df-b6e9-1f4511f3407b.png)

### アロー関数（デフォルト値の指定）

#### デフォルト値の指定なし

##### 記法
```javascript
const sayHello = (name) => 'こんにちは！' + name + 'さん';
```

##### 実行例
```javascript
console.log(sayHello());
```

##### 実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3911933/fb8f6ac0-9e23-c252-8896-ac9fcb98ecbe.png)

#### デフォルト値の指定あり

##### 記法
```javascript
const sayHello = (name = "ゲスト") => 'こんにちは！' + name + 'さん';
```

##### 実行例
```javascript
console.log(sayHello());
```

##### 実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3911933/b8630615-d67c-6d78-ecb5-b58572933a23.png)

# 2. テンプレート文字列

テンプレート文字列とは、文字列内にJavaScriptの変数を埋め込める記法のことです。
テンプレート文字列なしとありで、以下のように記法が異なります。

## テンプレート文字列なし

```javascript
const sayHello = (name) => 'こんにちは！' + name + 'さん';
```

## テンプレート文字列あり

```javascript
const sayHello = (name) => `こんにちは！${name}さん`;
```

テンプレート文字列ありだと、返却値が短く見やすくなりましたね！

# 3. オブジェクトの省略記法

オブジェクトのキー名と、値に指定した変数名が同一の名前だった場合、省略記法が使えます。
以下では、オブジェクトとの省略記法を使って、[アロー関数のところで紹介したコード](#例2)をさらにシンプルに記述してみました。

## オブジェクトの省略記法なし

```javascript
const getNameObj = (firstName, lastName) => ({
  firstName: firstName,
  lastName: lastName,
});
```

## オブジェクトの省略記法あり

```javascript
const getNameObj = (firstName, lastName) => ({
  firstName,
  lastName,
});
```

# 4. 分割代入

分割代入はオブジェクトや配列で使用できる、各要素を変数に代入する際の記法です。
以下では、オブジェクトと配列それぞれで使用例を記載しています。

## オブジェクトの分割代入

### 分割代入なし

#### 記法
```javascript
const myName = {
  firstName: '太郎',
  lastName: '山田',
};
const introduce = `私の名前は${myName.lastName}${myName.firstName}です！`;
```

#### 実行例

```javascript
console.log(introduce);
```

#### 実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3911933/a1ed432b-291c-1681-491e-014383e0cb86.png)

### 分割代入あり

```javascript
const myName = {
  firstName: '太郎',
  lastName: '山田',
};
const { firstName, lastName } = myName; // 分割代入
const introduce = `私の名前は${lastName}${firstName}です！`; // 分割代入の変数を使って記述可能
```

:::note warn
注意
分割代入の左辺で指定する変数は、オブジェクトに存在するキー名を指定する必要があります。
例えば、以下のように別の変数を定義した場合は値が取得できずundefinedになってしまいます。
:::

```javascript
const myName = {
  firstName: '太郎',
  lastName: '山田',
};
const { first, last } = myName; // オブジェクトに存在しないキーのため、undefinedが設定される
const introduce = `私の名前は${last}${first}です！`;
```
#### 実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3911933/4012894c-95cf-0233-b88f-eb2487f84001.png)

:::note
補足
分割代入の左辺で指定する変数の順番は、オブジェクトの並び順と一致していなくても問題ないようです。
:::

```javascript
const myName = {
  firstName: '太郎',
  lastName: '山田',
};
const { lastName, firstName } = myName; // ここの変数をオブジェクトの順番とは逆で記述
const introduce = `私の名前は${lastName}${firstName}です！`;
```
#### 実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3911933/837f34c5-e8db-b173-dd55-c17d8fe17a27.png)

### 分割代入あり（デフォルト値の指定）

#### デフォルト値の指定なし

##### 記法

```javascript
const myName = {
  lastName: '山田',
};
const { firstName, lastName } = myName; // オブジェクトに存在しないキーのため、undefinedが設定される
const introduce = `私の名前は${lastName}${firstName}です！`;
```

##### 実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3911933/e804587c-c917-4ea8-43d6-4ab109188398.png)

#### デフォルト値の指定あり

##### 記法

```javascript
const myName = {
  lastName: '山田',
};
const { firstName = '', lastName } = myName; // firstNameのデフォルト値を空で指定
const introduce = `私の名前は${lastName}${firstName}です！`;
```

##### 実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3911933/5fdaecb0-24d6-c68e-3b48-0f12d9981693.png)

## 配列の分割代入

### 分割代入なし

#### 記法

```javascript
const myName = ['太郎', '山田'];
const introduce = `私の名前は${myName[1]}${myName[0]}です！`;
```

#### 実行例

```javascript
console.log(introduce);
```

#### 実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3911933/22b0e814-de3e-8c3f-4868-ad4b6eb0d79b.png)

### 分割代入あり

```javascript
const myName = ['太郎', '山田'];
const [first, last] = myName; // 分割代入
const introduce = `私の名前は${last}${first}です！`; // 分割代入の変数を使って記述可能
```

:::note
POINT!
配列の分割代入の場合、任意の変数名を定義することが可能です。
:::

# 5. スプレッド構文

スプレッド構文は、配列操作の際に使用します。
いくつか利用パターンがあるので、以下でご紹介します。

## スプレッド構文の使用例1：配列の展開

関数の引数に、配列の値を割り当てるような使い方ができます。
以下は、引数で受けった値を乗算して返却する関数を例として記載しています。

### スプレッド構文なし

#### 記法

```javascript
const numbers = [2, 3];
const multiply = (num1, num2) => num1 * num2; 
```

#### 実行例

```javascript
console.log(multiply(numbers[0], numbers[1]));
```

#### 実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3911933/1b3fdcc1-09b5-f96e-ae7d-f9f8565d4023.png)

### スプレッド構文あり

```javascript
const numbers = [2, 3];
const multiply = (num1, num2) => num1 * num2; 
```

#### 実行例

```javascript
console.log(multiply(...numbers)); // スプレッド構文
```

## スプレッド構文の使用例2：分割代入で値をまとめて配列で取得

例えば数値が格納されている配列があり、以下のように値を取得したいとします。
- 最初の要素を変数（firstNumber）に格納
- 残りの全ての値を配列（otherNumbers）に格納

この場合、分割代入とスプレッド構文を組み合わせることで実現できます。

### 記法

```javascript
const numbers = [1,2,3,4,5];
const [firstNumber, ...otherNumbers] = numbers;
```

### 実行例

```javascript
console.log(firstNumber);
console.log(otherNumbers);
```

### 実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3911933/931c563c-a064-8610-e459-105eeca86d32.png)

スプレッド構文を使用しない場合は煩雑な実装になりそうなところですが、スプレッド構文を使用することで1行で記述できました。

## スプレッド構文の使用例3：配列のコピー

### 補足：配列の参照渡し

:::note alert
配列のコピーを行い新規の配列を作成する場合、変数の代入のように
`const fruits2 = fruits1;`
と記述したくなりますが、これはNGです。
以下に理由を説明します。
:::

#### 記法

```javascript
const fruits1 = ['りんご', 'みかん'];
const fruits2 = fruits1;
```

#### 実行例

```javascript
console.log(fruits1);
console.log(fruits2);
```

#### 実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3911933/abc916ee-a483-710c-95d5-64e10ece5021.png)

例えばここで、fruits1の要素を更新してみます。

#### 記法

```javascript
const fruits1 = ['りんご', 'みかん'];
const fruits2 = fruits1;
fruits1[0] = 'メロン';
```

#### 実行例

```javascript
console.log(fruits1);
console.log(fruits2);
```

#### 実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3911933/956ba935-c3a3-b6f5-fca1-9d97b3354d10.png)

fruits1の要素を変更したのに、fruits2の要素も更新されてしまいました。

これは、fruits2に代入する際、fruits1の中身をコピーして新しい配列を作成しているわけではなく、**fruits1が参照しているメモリ上のアドレス（どこにデータが格納されているかの情報）を渡しているだけだから**です。

fruits1、fruits2は同じ場所に格納されている値を参照しているため、参照元の値が変わることで、両方の配列の中身が変わってしまいます。

~~なお、参照元の情報を渡すことを「**参照渡し**」と呼びます。
逆に、値をコピーして渡すことを「**値渡し**」と呼びます。~~
→上記につきまして、JavaScriptには参照渡しは存在しないとのことで、誤りでした。
　理解不足により誤った記載をしてしまい申し訳ございません。

この違いを理解していないと思わぬバグが生まれてしまいそうなので、自分も注意していきたいと思います。

### スプレッド構文あり

前置きが長くなりましたが、スプレッド構文を利用し配列の値をコピーして新しい配列を作成する方法をご紹介します。

#### 記法

```javascript
const fruits1 = ['りんご', 'みかん'];
const fruits2 = [...fruits1];
```

#### 実行例

```javascript
console.log(fruits1);
console.log(fruits2);
```

#### 実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3911933/4dcbe021-6af0-ac2a-d16d-d92ed184ee0f.png)

こちらも1行で記載できましたね。
念のため、要素を更新した際の挙動も確認してみます。

#### 記法

```javascript
const fruits1 = ['りんご', 'みかん'];
const fruits2 = [...fruits1];
fruits1[0] = 'メロン';
```

#### 実行例

```javascript
console.log(fruits1);
console.log(fruits2);
```

#### 実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3911933/83a54b1d-9557-e2cd-2bca-d6f66f751097.png)

## スプレッド構文の使用例4：配列の結合

スプレッド構文を使用することで、複数の配列を結合して新たな配列を作成することも簡単に行えます。

### 記法

```javascript
const fruits1 = ['りんご', 'みかん'];
const fruits2 = ['バナナ', 'ぶどう', 'いちご'];
const allFruits = [...fruits1, ...fruits2];
```

### 実行例

```javascript
console.log(allFruits);
```

### 実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3911933/7f230ed4-0471-bcf5-b137-edfb0e92dc60.png)

# おわりに

こうしてみると、JavaScriptには様々な記法がありますね。

知っておくと複雑な処理を1行で書けたり、視認性が高められたりとメリットも多いと思いますので、開発時にうまく活用していきたいと思います！

# 参考

https://www.udemy.com/course/modern_javascipt_react_beginner/?couponCode=BASIC20241001