JavaScriptの連想配列周りメモ

# 概要
- JavaScriptの連想配列についてシンプルに解説します

# シンプル解説
- 例えば、 以下の猫のデータを扱う事を考えます

| 項目 | 値 |
|  ---  |  ---  |
| 名前 | らべ |
| 好きな食べ物 | 銀のスプーン |
| 好きなおやつ | ちゅーる |

## 配列を使う

```js
const cat = ['らべ', '銀のスプーン', 'ちゅーる'];
```

例えばこのデータから「好きな食べ物」を取り出して出力する場合は配列の何番目かをプログラムに書くことになります。

```js
const cat = ['らべ', '銀のスプーン', 'ちゅーる'];
const result = `好きな食べ物は 「${cat[1]}」です`;
console.log(result);
```

結果は

```
好きな食べ物は 「銀のスプーン」です
```

この後項目が増えて

| 項目 | 値 |
|  ---  |  ---  |
| 名前 | らべ |
| なりたい動物 | 人間 |
| 好きな食べ物 | 銀のスプーン |
| 好きなおやつ | ちゅーる |

と増えた時、もし以下のプログラムで配列の何番目かを変え忘れてしまうと…

```js
const cat = ['らべ', '人間', '銀のスプーン', 'ちゅーる']; // なりたい動物を追加
const result = `好きな食べ物は 「${cat[1]}」です`;
console.log(result);
```

結果は

```
好きな食べ物は 「人間」です
```

と、ヤバい猫になってしまいます。

もしあちこちで「catの配列の何番目か」ってコードを書いてたら、全部の数字を修正しないといけないですよね（汗）
これを解決するのが、オブジェクトってやつです。

## オブジェクトを使う

```js
const cat = {
  '名前': 'らべ',
  '好きな食べ物': '銀のスプーン',
  '好きなおやつ': 'ちゅーる'
};
const result = `好きな食べ物は 「${cat.好きな食べ物}」です`;
console.log(result);
```

結果は

```
好きな食べ物は 「銀のスプーン」です
```

こんな風に、項目と値のペアでデータを持てるんですよね。
`cat.好きな食べ物` という形で扱うことができれば中に何が入っているか連想しやすいですよね。
それに、さっきのように項目が追加されても、`${cat.好きな食べ物}` の部分は変更する必要はありません。

```js
const cat = {
  '名前': 'らべ',
  'なりたい動物': '人間',
  '好きな食べ物': '銀のスプーン',
  '好きなおやつ': 'ちゅーる'
};
const result = `好きな食べ物は 「${cat.好きな食べ物}」です`;
console.log(result);
```

結果は

```
好きな食べ物は 「銀のスプーン」です
```

このように、データに項目名のようなものが欲しい場合は、配列ではなくオブジェクトを使うのが良さそうですね。
しかし、JavaScriptではオブジェクト＝連想配列なのでしょうか？

## ん？オブジェクトは「配列」？？？

しかしもって、オブジェクトは配列ではありません（泣）
オブジェクトは配列のように中にデータがいくつ入っているかというプロパティはありません。

#### 配列

```js
const cat = ['らべ', '人間', '銀のスプーン', 'ちゅーる'];
console.log(cat.length) // 結果は「4」
```

#### オブジェクト

```js
const cat = {
  '名前': 'らべ',
  'なりたい動物': '人間',
  '好きな食べ物': '銀のスプーン',
  '好きなおやつ': 'ちゅーる'
};
console.log(cat.length) // 結果は「undefined」
```

つまり、オブジェクトは「連想」はできますが「配列」ではないのです。

## Mapを使う

オブジェクトは連想配列として生まれたわけではないので、JavaScriptでは連想配列に近いものを用意することになりました。
それが「Map」です。2015年に登場しました。

```js
const cat = new Map();
cat.set('名前', 'らべ');
cat.set('なりたい動物', '人間');
cat.set('好きな食べ物', '銀のスプーン');
cat.set('好きなおやつ', 'ちゅーる');
const result = `好きな食べ物は 「${cat.get('好きな食べ物')}」です`;
console.log(result);
```

結果は

```
好きな食べ物は 「銀のスプーン」です
```

もちろん個数も取れます。

```js
const cat = new Map();
cat.set('名前', 'らべ');
cat.set('なりたい動物', '人間');
cat.set('好きな食べ物', '銀のスプーン');
cat.set('好きなおやつ', 'ちゅーる');
const result = `好きな食べ物は 「${cat.get('好きな食べ物')}」です`;
console.log(cat.size) // 結果は「4」
```

なので、連想配列を実現したいときは、一番連想配列に近いMapを使いましょう！

とは現実ではなかなかならず…

# オブジェクト便利すぎ問題

JavaScriptのデータ形式と言えばJSONです。
JSONはJavaScript以外の世界でも広がっており、CSVに代わる「プログラミングにおけるデータ形式の代名詞」というところまでになっています。
JSON形式のデータは、いわゆるオブジェクトを文字列化したもので、JSONとの兼ね合いで**「オブジェクトを使う事自体がメリット」**となっている実情があります。
MapはJSONとの相性があまり良くないんですよね…（MapからJSONへの変換が難しい等）
オブジェクトに慣れちゃうと、「あれ、Map形式じゃん…使いづらい…」となってしまうのが現実です。

# オブジェクトで個数を取得するには？

`Object.keys()` という関数を使うと、オブジェクトに入っている項目名を配列で取得できるんですよね。

```js
const cat = {
  '名前': 'らべ',
  'なりたい動物': '人間',
  '好きな食べ物': '銀のスプーン',
  '好きなおやつ': 'ちゅーる'
};
console.log(Object.keys(cat));
```

結果は

```
["名前", "なりたい動物", "好きな食べ物", "好きなおやつ"]
```

この配列の個数を数えることができれば、良いわけです。

```js
const cat = {
  '名前': 'らべ',
  'なりたい動物': '人間',
  '好きな食べ物': '銀のスプーン',
  '好きなおやつ': 'ちゅーる'
};
console.log(Object.keys(cat).length); // 4
```

# オブジェクトを配列のようにループするには？

上でオブジェクトの要素名の配列を取得できたので、それをループすれば良いわけです。
ちなみにfor-in文でもできます。(for-of文は使えません。ややこしいですね。)

```js
const cat = {
  '名前': 'らべ',
  'なりたい動物': '人間',
  '好きな食べ物': '銀のスプーン',
  '好きなおやつ': 'ちゅーる'
};
Object.keys(cat).forEach((key) => {
  console.log(`項目名: 「${key}」 の中身は 「${cat[key]}」`);
});
```

結果は

```
項目名: 「名前」 の中身は 「らべ」
項目名: 「なりたい動物」 の中身は 「人間」
項目名: 「好きな食べ物」 の中身は 「銀のスプーン」
項目名: 「好きなおやつ」 の中身は 「ちゅーる」
```

# まとめ
- 連想配列とは、配列の中身を分かりやすくするために、「何番目か」ではなく「中身に何が入っているかの項目名」をつけた配列のこと
- JavaScriptは「オブジェクト」が「連想配列代わり」に使われている
- 「オブジェクト」は「配列ではない」
- JavaScriptでは連想配列に近いものとしてMapが2015年に誕生したが、JSONが普及しすぎたのもあって、Mapを使うよりオブジェクトを連想配列のように使われている実情がある
- オブジェクトを配列代わりにして、個数を求めたりループしたりするやり方が、ややハックっぽいけどある