4歳娘「パパ、懐かしいJavaScript書いてるね！」

## リモートワーク中ワイ
ワイ「お、社長からメールや！」
ワイ「また何か仕事をさせる気やな・・・！」

よめ太郎「（**そらせやろ**）」

ワイ「どれどれ・・・」

> `["たかし", 37, 173, 75]`
> ↑この配列を元にオブジェクトを作ってくれ。
>
> 配列の中の4つの値は、それぞれ**名前・年齢・身長・体重**やで。

ワイ「ふーん」
ワイ「何やこの意味わからん仕事」
ワイ「まあええか、やってみよ」

## やってみる

ワイ「まず、元の配列は・・・」

```javascript:JavaScript
const array = ["たかし", 37, 173, 75];
```
ワイ「↑こうやな」
ワイ「ほんで、この配列の中の**4つの値**は」
ワイ「それぞれ**名前・年齢・身長・体重**を表しとるんやったな」
ワイ「ほな、分かりやすいように名前をつけたろか」

```javascript:JavaScript
const array = ["たかし", 37, 173, 75];

const name = array[0];
const age = array[1];
const height = array[2];
const weight = array[3];
```

ワイ「↑こうやな」

娘（**4歳**）「**パパ、懐かしいJavaScript書いてるね！**」

ワイ「・・・と言いますと？」

## 分割代入

娘「いまどきは、**分割代入**を使って↓こう書けばいいんじゃない？」

```javascript:JavaScript
const array = ["たかし", 37, 173, 75];

const [name, age, height, weight] = array;
```

ワイ「**ファッ！？**」
ワイ「これで`name, age, height, weight`っていう**4つの変数**を定義できるんか」

娘「そうだよ」
娘「ちなみに、`name`と`age`だけ使いたい場合は」

```javascript:JavaScript
const [name, age] = array;
```
娘「↑こうも書けるよ」

ワイ「おお、後ろのほうの値は使わんこともできるんか」

娘「うん」
娘「逆に、後ろのほうの値だけを使うこともできるよ」

```javascript:JavaScript
const [, , height, weight] = array;
```

娘「↑こうだね」

ワイ「おお」
ワイ「ありがとう、娘ちゃん・・・」

## そこからオブジェクトを作る

ワイ「ほんで、オブジェクトを作らなあかんのやったな」
ワイ「ほな・・・」

```javascript:JavaScript
const takashi = {
  name: name,
  age: age,
  height: height,
  weight: weight
};
```

ワイ「↑これでええか」

娘「もうちょっと楽に書けるよ」

```javascript:JavaScript
const takashi = {
  name,
  age,
  height,
  weight
};
```

娘「↑これでいいんだよ」

ワイ「おお」
ワイ「**変数名**が**キー名**と同じ場合は」
ワイ「そう書くだけでええんやね」

## 社長から次の指示

> 追加でお願いや。
>
> `["ひろゆき", 48, 175, 65]`
↑この配列もオブジェクトにしてほしいんや。

ワイ「また似たような仕事やな」
ワイ「これはさっきの処理の使い回しでイケるな」
ワイ「ほな、さっきの処理を関数にして、使い回せるようにしておこか」
ワイ「**配列**を受け取って、**オブジェクト**を返す関数やから・・・」

```javascript:JavaScript
const makePerson = (array) => {
  const [name, age, height, weight] = array;

  return {
    name,
    age,
    height,
    weight
  };
}
```

ワイ「↑こうやな！」
ワイ「人間っぽいオブジェクトを作るから、関数名は`makePerson`や！」
ワイ「この`makePerson`にさっきの配列を渡してやればええわけやから・・・」

```javascript:JavaScript
const hiroyuki = makePerson(["ひろゆき", 48, 175, 65]);
```

ワイ「↑こうや！」

娘「さっそく分割代入を使ってるんだね」
娘「さすがパパ！」

ワイ「ゲヘヘ」

娘「でもね、分割代入は**引数を受け取るとき**にも使えるから」

```javascript:JavaScript
const makePerson = ([name, age, height, weight]) => {
  return {
    name,
    age,
    height,
    weight
  };
}
```

娘「↑こうでいいんだよ」

ワイ「おお、楽チンやな」
ワイ「ん？社長からまたメールや」

## またまた追加指示

> さっき作った**人間オブジェクト**を元に
「こんにちは！私はたかし！37歳だよ！」っていうテキストを生成する、
**挨拶関数**を作ってくれや。

ワイ「挨拶関数か。楽勝やな！」
ワイ「**人間オブジェクト**を受け取って、**文字列**を返す関数やから・・・」

```javascript:JavaScript
const makeGreetingText = (person) => {
  const name = person.name;
  const age = person.age;
  return "こんにちは！私は" + name + "！" + age + "歳だよ！";
};
```

ワイ「↑こうやな！」

娘「パパ、**オブジェクトからも分割代入できる**よ」

ワイ「と言いますと？」

娘「つまり・・・」

```javascript:JavaScript
const makeGreetingText = ({name, age}) => {
  return "こんにちは！私は" + name + "！" + age + "歳だよ！";
};
```

娘「↑これでいいってこと」

ワイ「Oh...素敵やん」
ワイ「ってことは例えば・・・」

```javascript:JavaScript
const {name, age} = person;
```

ワイ「↑こういう書き方もできるんやね」

娘「そうそう」

ワイ「でも、`person.name`と`person.age`を」
ワイ「`userName`とか`userAge`みたいな、**ちょっと違う名前**の変数に入れたい場合は・・・」

```javascript:JavaScript
const userName = person.name;
const userAge = person.age;
```

ワイ「↑こう書くしかないんかな・・・？」

娘「ええとね」
娘「その場合は・・・」

```javascript:JavaScript
const {name: userName, age: userAge} = person;
```

娘「こう書けばいいんだよ」

ワイ「おお、オブジェクトのプロパティ名と**異なる名前**の変数にもできるんや」

娘「うん」
娘「あとね・・・」
娘「文字列と変数を連結させてる部分も・・・」

## テンプレート文字列

娘「↓こっちの方がいいかも」

```javascript:JavaScript
return `こんにちは！私は${name}！${age}歳だよ！`;
```

娘「**テンプレート文字列**ってやつだね」

ワイ「ほええ、文字列の中で**変数の中身を展開**してくれるんやね」
ワイ「なんや、PHPみたいやな」

## またまたまた追加指示

ワイ「また社長からメールが来たで」

> **たかし**には双子の弟がおるんや。
名前は**いちろう**や。
**いちろう**もオブジェクトにしてあげてや。
>
> 名前以外は、**たかし**と**全く同じ**や。

ワイ「たかしの弟が**いちろう**って、どないなっとんねん」
ワイ「たかし、無かったことにされとるやないか」
ワイ「まあええわ」
ワイ「**たかし**をコピーして作ればええやろ」
ワイ「配列をコピーするには、↓こうやな！」

```javascript:JavaScript
const array = ["たかし", 37, 173, 75];
const copiedArray = [].concat(array);
```

ワイ「配列が持っとる`concat`メソッドを使って」
ワイ「**空配列**に、**コピー元の配列**を連結してやると」
ワイ「配列をコピーできるんや」

娘「それでもいいけど・・・」

## スプレッド構文

娘「↓こうも書けるよ」

```javascript:JavaScript
const array = ["たかし", 37, 173, 75];
const copiedArray = [...array];
```

娘「`...array`は**スプレッド構文**ってやつだね」
娘「配列を**展開してくれる**やつ」

ワイ「配列を**展開**・・・？」
ワイ「**展開**とは・・・？」

娘「ええと」

```javascript:JavaScript
["たかし", 37, 173, 75]
```

娘「↑この配列を」

```javascript:JavaScript
...["たかし", 37, 173, 75]
```

娘「↑こう**スプレッド構文**で**展開**すると」

```javascript:JavaScript
"たかし", 37, 173, 75
```

娘「↑こうしてくれる感じだね」
娘「両端にある`[`と`]`を取ってくれる感じ」
娘「だから、**展開**」

ワイ「なるほど、たしかに**展開**って感じやな」
ワイ「つまり」

```javascript:JavaScript
const copiedArray = [...array];
```

ワイ「↑これはどうなるんや？」
ワイ「`array`には`["たかし", 37, 173, 75]`が入っとるわけやから」

```javascript:JavaScript
const copiedArray = [...["たかし", 37, 173, 75]];
```

ワイ「↑こういうことやな？」
ワイ「ほんで、`...`が付いとるから」
ワイ「`["たかし", 37, 173, 75]`が**展開**されて」
ワイ「`"たかし", 37, 173, 75`になって」

```javascript:JavaScript
const copiedArray = ["たかし", 37, 173, 75];
```

ワイ「↑こういう意味になるってことか」
ワイ「だから配列がコピーされるんやな」

娘「そうそう」
娘「でも、**一段階**だけの**シャローコピー**（浅いコピー）だから注意してね？」
娘「配列の中に、更に配列が入ってたり、オブジェクトが入っている場合は」
娘「**完全に複製されるわけではない**から」

ワイ「せやったな」

娘「スプレッド構文は、**複数の配列を連結させる**ときにも使えるよ」

```javascript:JavaScript
const a = [1, 2, 3];
const b = [4, 5, 6];
const c = [7, 8, 9];

const abc = [...a, ...b, ...c];
```

娘「↑こうすると」

```javascript:JavaScript
[1, 2, 3, 4, 5, 6, 7, 8, 9]
```

娘「↑こんな配列ができあがるの」

ワイ「おお、`concat`メソッドより直感的やな！」
ワイ「書きやすいし、読みやすい気がするわ！」

## 双子の弟「いちろう」を作る

ワイ「これで双子の弟**『いちろう』**を作ることができるな」

```javascript:JavaScript
const array = ["たかし", 37, 173, 75];
const copiedArray = [...array];
copiedArray[0] = "いちろう";
```

ワイ「↑こんな感じで、名前だけ`"いちろう"`に変えてやって・・・」

```javascript:JavaScript
const ichiro = makePerson(copiedArray);
```

ワイ「`makePerson`関数でオブジェクトにしてやればええんや」

娘「それでもいいけど、さっき`takashi`っていうオブジェクトを作ったんだから」
娘「`takashi`をコピーして`name`だけ変えてもいいんじゃない？」

ワイ「そうか」

```javascript:JavaScript
const ichiro = takashi;
ichiro.name = "いちろう";
```

ワイ「↑こうやな！」

娘「いや、それだと`takashi`も`ichiro`も**同じオブジェクトを指している**ことになっちゃうから」
娘「`takashi`の`name`も`"いちろう"`になっちゃうよ」
娘「ていうか**同一人物**になっちゃうじゃん」

ワイ「まあ、双子なんやし、同一人物みたいなもんやろ・・・」

娘「**いやいや全然違うでしょ**」
娘「**タッチファン**に◯されるよ？」

ワイ「なるほど、想像してみたら確かに**マズイ**わ」
ワイ「ほな、ちゃんとオブジェクトを**複製**せなあかんのやな」

```javascript:JavaScript
const ichiro = Object.assign({}, takashi);
ichiro.name = "いちろう";
```

ワイ「↑こうやな！」
ワイ「`Object.assign`メソッドで」
ワイ「**空オブジェクト**に`takashi`をマージしてやることで」
ワイ「`takashi`の複製を作ってやんねん」

娘「そんなときも、さっきの配列の時みたいに」
娘「**スプレッド構文**が使えるよ！」

```javascript:JavaScript
const ichiro = {...takashi};
ichiro.name = "いちろう";
```

娘「↑こうだね」
娘「さらに・・・」

```javascript:JavaScript
const ichiro = {
  ...takashi,
  name: "いちろう"
};
```

娘「↑こうも書けるよ！」

ワイ「ええ、何やその書き方」
ワイ「えらいスッキリ書けるんやな」
ワイ「ええと、スプレッド構文は**両端のカッコを外してくれる**イメージやったな・・・」

```javascript:JavaScript
const ichiro = {
  ...takashi,
  name: "いちろう"
};
```

ワイ「↑この`takashi`には・・・」
ワイ「`{name: "たかし", age: 37, height: 173, weight: 75}`が入ってるから・・・」

```javascript:JavaScript
const ichiro = {
  ...{
    name: "たかし",
    age: 37,
    height: 173,
    weight: 75
  },
  name: "いちろう"
};
```

ワイ「↑こんなイメージか」
ワイ「ほんで、スプレッド構文が**両端のカッコを外して展開**してくれるから・・・」

```javascript:JavaScript
const ichiro = {
  name: "たかし",
  age: 37,
  height: 173,
  weight: 75,
  name: "いちろう"
};
```

ワイ「こんなイメージやな」
ワイ「あれ、`name`が2つになってしもうたで」

娘「その場合は、より後ろにある`name`で**上書き**されるよ」

ワイ「ほな結局・・・」

```javascript:JavaScript
const ichiro = {
  ...takashi,
  name: "いちろう"
};
```

ワイ「↑この書き方をすると」

```javascript:JavaScript
const ichiro = {
  name: "いちろう",
  age: 37,
  height: 173,
  weight: 75
};
```

ワイ「↑こういう感じになるわけか」
ワイ「オブジェクトをコピーしつつ、`name`だけ上書き、みたいな」
ワイ「便利な時代になったもんやなぁ・・・」

娘「これも**シャローコピー**だから気をつけてね」

## 次は何をする

ワイ「ほんで結局、この`takashi`や`ichiro`を使って」
ワイ「何をすればええんやろ」
ワイ「メールで社長に聞いてみよか」

> ワイ「`takashi`と`ichiro`作りましたで」
> ワイ「次は何をするんか教えてや」

ワイ「これでよし、と」
ワイ「おっ」
ワイ「さっそくお返事が来たで」

> 社長「いや**何をする**とかではないねん」
> 社長「ただちょっと・・・」
社長「・・・作ってみてほしかったんや」

ワイ「・・・」
ワイ「何やそれ！」
ワイ「酒飲む時間がなくなってもうたやんけ！」

よめ太郎「レガシー記法を脱却できたし」
よめ太郎「酒量も減るし、よかったやん」

**〜おしまい〜**

## この記事もよろしくやで！
[**4歳娘「パパ、constしか使わないで？」**](https://qiita.com/Yametaro/items/17f5a0434afa9b88c3b1)

## 参考文献

+ [分割代入 - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)
+ [テンプレート文字列 - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/template_strings)
+ [代入 - uhyohyo.net](https://uhyohyo.net/javascript/16_3.html)