【JS / TS】Hooks がわからんのではない、分割代入をわかっていないだけ（オブジェクト編）

## 0.はじめに

React の props, Hooks の動きがわからず、何度も調べては忘れてを繰り返していました。

これは、props や Hooks をわかっていないんじゃなくて、JavaScript の**分割代入をわかっていないだけ**でした。

「分割代入まじわからん」  
って状態だったので、思考を整理するためにこの記事を書きました。

なので、初学者向けの記事となっています。

間違って解釈している所ありましたら、ご指摘いただけますと幸いです。

## 1.この記事を読んだら、できるようになること

:::note info

「分割代入まじわからん」を克服できます。

下記の分割代入を理解できます。

- **オブジェクトの分割代入 ← 今回はここ**
- 配列の分割代入
- 複雑な分割代入

:::

最終的には、こんな分割代入を理解できるようになります。

```ts:
const {
	nickname: userName = '名無し',
	age = 132,
	programmingSkills: {
		frontEnd: [
			[firstFrontEndLanguage, ...otherFrontEndLanguage],
			[firstFrontEndFW, ...otherFrontEndFW]
		],
		backEnd: [
			[firstBackEndLanguage, ...otherBackEndLanguage],
			[firstBackEndFW, ...otherBackEndFW]
		],
		infra
	}
} = user;
```


記事が長くなりそうなので、分割代入の記事を分割して書きます😏  
今回は、**分割代入のオブジェクト編**になります。

## 2.目次


[0. はじめに](https://qiita.com/daishiman/items/5acf803f252b82f970fe#0%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB)  
[1. この記事を読んだら、できるようになること](#1この記事を読んだらできるようになること)  
[2. 目次](#2目次)  
[3. 環境](#3環境)  
[4. 分割代入とは](#4分割代入とは)  
[5. オブジェクトの分割代入](#5オブジェクトの分割代入) **← ここまで**    
[6. 配列の分割代入](https://qiita.com/daishiman/items/324dcc0eae72eb6b13cf#6%E9%85%8D%E5%88%97%E3%81%AE%E5%88%86%E5%89%B2%E4%BB%A3%E5%85%A5)  
[7. 複雑な分割代入](https://qiita.com/daishiman/items/d382279a2a6cae3ea1aa#7-%E8%A4%87%E9%9B%91%E3%81%AA%E5%88%86%E5%89%B2%E4%BB%A3%E5%85%A5)


## 3.環境

- TypeScript: 4.7.4

## 4.分割代入とは


オブジェクトや配列から値を取りだして変数に代入する操作を簡略化したものです。

下記のように書くことができます。

```ts:
// オブジェクトの分割代入
const { name, age } = user;

// 配列の分割代入
const [firstSkill, secondSkill] = programmingSkills;
```

[0.はじめ](https://qiita.com/daishiman/items/5acf803f252b82f970fe#0%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB) にも書きましたが、  
私はこれがどういう動きをしているのかが理解できていませんでした。

これがどのような動きをしているのかを説明していきます。

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

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

下記が、オブジェクトの分割代入となります。

```ts:
// オブジェクトの分割代入
const { name, age } = user;
```

これがどのような意味なのかを以下で説明していきます。

#### 5.1.1.使用するオブジェクト

下記のオブジェクトを使用して、分割代入の挙動を確認したいと思います。

```ts:
type User = {
	nickname: string;
	age: number;
}

const user: User = {
	nickname: 'daishi',
	age: 35,
};
```


#### 5.1.2.分割代入で記述

下記のように、分割代入で記述すると、  
**複数の変数定義を１行で書くことができます。**

```ts:
const { nickname, age } = user;

// 実行
console.log(nickname); // daishi
console.log(age);      // 35
```

ただ、`nickname`, `age` を実行するとなぜ、  
`daishi`, `35` が返ってくるのか理解に苦しみました。

#### 5.1.3.分割代入を使用しないで記述

これを分割代入を使用せずに記述してみます。  
そうすると、どのような動きをするのかが理解できるかと思います。

```ts:
const nickname = user.nickname;
const age      = user.age;

// 実行
console.log(nickname); // daishi
console.log(age);      // 35
```

これは、  
- `nickname` 変数の中に、`user` オブジェクトの `nickname` プロパティを入れる  
- `age` 変数の中に、`user` オブジェクトの `age` プロパティを入れる

という意味になりますよね。

つまり、

```ts:
const { nickname, age } = user;
```

というのは、

```ts:
const nickname = user.nickname;
const age      = user.age;
```

を省略して記述していることになります。  

:::note info

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

- 左辺に`｛｝`の中に変数を、右辺に使用するオブジェクトを記述する
    (※ 左辺の変数名と右辺のプロパティ名が同じでなければならない)
- 複数のオブジェクトのプロパティの変数定義を省略できる
- 取りだしたいプロパティの記述を省略できる

:::

理解できると、めちゃ便利だなと感じますねw

#### 5.1.4.プロパティとは別名の変数にいれる

ただ上記の書き方だと、  
変数名はプロパティ名と同じでないといけません。

**プロパティ名とは別の変数名をつけたい**ときは、下記のようにします。

```ts
const { nickname: userName, age } = user;

// 実行
console.log(userName); // daishi
```

`nickname: userName` とすることで、`userName` という変数名をつけることができます。

```ts:
const userName = user.nickname;
``` 

という意味になります。

:::note alert
`nickname` で実行するとコンパイルエラーとなるので注意して下さい。
:::



### 5.2.オブジェクトの中にオブジェクトがネストした分割代入

次に、オブジェクトの中にオブジェクトがネストしている場合はどのような記述をするのかを見ていきたいと思います。

#### 5.2.1.使用するオブジェクト

下記のオブジェクトを用いたいと思います。

```ts:
type User = {
	nickname: string;
	age: number;
	programmingSkills: {
		frontEnd: string;
		backEnd: string;
	}
}

const user: User = {
	nickname: 'daishi',
	age: 35,
	programmingSkills: {
		frontEnd: 'JavaScript',
		backEnd: 'PHP',
	}
};
```

#### 5.2.2.分割代入で記述

```ts:
const { nickname, age, programmingSkills: { frontEnd, backEnd } } = user;

// 実行
console.log(nickname); // daishi
console.log(age);      // 35
console.log(frontEnd); // JaveScript
console.log(backEnd);  // PHP
```

ネストすると少し複雑に感じるかもしれませんが、  
先程と同じように分割代入を用いずに記述してみるとわかりやすいかと思います。

#### 5.2.3.分割代入を使用しないで記述

```ts:
const nickname = user.nickname;
const age      = user.age;
const frontEnd = user.programmingSkills.frontEnd;
const backEnd  = user.programmingSkills.backEnd;

// 実行
console.log(nickname);	// daishi
console.log(age); 		// 35
console.log(frontEnd);	// JaveScript
console.log(backEnd);	// PHP
```

オブジェクトがネストしたときは、  

```ts
{ programmingSkills: { frontEnd, backEnd } } = user;
```

のように、  
**オブジェクトの中オブジェクトに、変数名（プロパティ名）を記述**するだけです。

これも、分割代入を用いない方法と比較すると理解しやすいかと思います。

### 5.3.オブジェクトの中の一部のみ使用したいとき

ここまで、オブジェクトのプロパティの全てを分割代入で記述しましたが、  
**プロパティの一部分だけ代入したい**ということがあるかと思います。  
（ほとんがこの使い方ですよね…）

そのときは、次のようにして使います。

```ts:
const { nickname, programmingSkills: { frontEnd } } = user;

// 実行
console.log(nickname); // daishi
console.log(frontEnd); // JaveScript
```

単純に、使用したいプロパティのみ記述するだけです。  
説明するまでもないかもですが…w


### 5.4.デフォルト値

分割代入には、デフォルト値を指定することができます。


#### 5.4.1.使用するオブジェクト

下記のような **空のオブジェクト** があったとします。

```ts:
type User = {
	nickname?: string;
	age?: number;
	programmingSkills?: {
		frontEnd?: string;
		backEnd?: string;
	}
}

const user: User = {};
```

#### 5.4.2.分割代入で記述

```ts:
const { nickname, age, programmingSkills } = user;

// 実行
console.log(nickname);          // undefined
console.log(age);               // undefined
console.log(programmingSkills); // undefined
```

当たり前ですが、空のオブジェクトなので、各それぞれ、**undefined** という結果が返ってきます。

#### 5.4.3.デフォルト値の設定

未定義のときに、デフォルト値が入っていると便利なときがあります。

例えば、`nickname` が空のときは、**匿名** をデフォルトで入って欲しいなどです。

デフォルト値を設定したいときは、下記のように書くことができます。

```ts:
const { nickname = '名無しの権兵衛', age, programmingSkills } = user;

// 実行
console.log(nickname);          // 名無しの権兵衛
console.log(age);               // undefined
console.log(programmingSkills); // undefined
```

:::note info

`nickname = '名無しの権兵衛'` のように  
**`{ 変数 = デフォルト値 } = オブジェクト;`**

と記述するとデフォルト値を設定することができます。

:::

:::note alert

注意点  
デフォルト値を設定するときは、**undefined** の定義が必要です。  
これは、デフォルト値が入る前に、**undefined** で弾かれてしまうからです。

:::


### 5.5.まとめ

分割代入で記述する方法と分割代入で記述しない方法で比較すると、分割代入を理解することができました。

併せて他の記事も読んでいただけると嬉しいです🙇‍♂️

https://qiita.com/daishiman/items/324dcc0eae72eb6b13cf

https://qiita.com/daishiman/items/d382279a2a6cae3ea1aa


## 参考
[書籍：プロを目指す人のためのTypeScript入門　鈴木僚太［著］](https://twitter.com/uhyo_/status/1517158176365641729?s=20&t=5jZBSZVbLrAsgkCUruO7Ig)