JavaScriptオブジェクト理解

# 初めに

本記事は「開眼！JavaScript」という書籍の備忘録的なまとめ。詳しく知りたい方は購入して読んでみて下さい。

## けっきょく、オブジェクト。

オブジェクトを理解すれば、JavaScriptを理解できます。

「**オブジェクトとは、名前と値を持つプロパティを格納するコンテナに過ぎない**」

この一文を心に刻んでおいて下さい。

```jsx
const person = {name: "Jane", age: "24"}
console.log(person.name,person.age)
```

## 兎にも角にも、Objectを生成する。

まずは空のオブジェクトを生成してみましょう。

生成方法は２パターンあります。

- **リテラル記法**を使用する方法

```jsx
const obj = {};
console.log(obj)
```

- newオペレータ（Object()コンストラクタ）を使用する方法

```jsx
const obj = new Object();
console.log(obj)
```

現在は**リテラル記法**を使用する方法が一般的です。ログに出力してみると、どちらもオブジェクトであることがわかります。

ここで覚えておいてほしいワードを二つ挙げます。

- **コンストラクタ**
- **インスタンス**

### コンストラクタ

コンストラクタは、新しいオブジェクトのインスタンスを生成するための特別な関数です。**`new`オペレータと共に使用されることが多いです。JavaScriptでは、`Object`**, **`Array`**, **`Date`**など、組み込みのコンストラクタ関数があり、これらを使用して様々な種類のオブジェクトを生成することができます。

```jsx
new Object()
new Array()
new Date()

```

### インスタンス

コンストラクタから返されたオブジェクトのことを**インスタンス**と呼びます。

したがって、リテラル記法で生成されたオブジェクトも、技術的には**`Object`**コンストラクタのインスタンスとみなすことができますが、**コンストラクタ関数を明示的に呼び出しているわけではない**という点で異なります。リテラル記法はJavaScriptにおいてオブジェクトを生成するための簡潔な記法です。

要は、new Object()が行うことを**隠蔽している**に過ぎないということです。

```jsx
const contructObj = new Object()
const literalObj = {}

```

## オブジェクトで多次元配列を実現

オブジェクトはとても自由な表現ができます。

以下のコードを繰り返しで各プロパティをコンソールに出力してみて下さい。

```jsx
const personArrayObj = [
  {
    personal: {
      name: "Jane",
      age: "24",
      sex: "man",
      prefecture: "Tokyo",
    },
    company: {
      name: "Techno Solutions",
      prefecture: "fukushima",
    },
  },
  {
    personal: {
      name: "Doe",
      age: "20",
      sex: "woman",
      prefecture: "Saitama",
    },
    company: {
      name: "Techno Solutions",
      prefecture: "fukushima",
    },
  },
];

```

出力できましたか？

以下のコードでpersonObjの名前だけを出力しています。

```jsx
personArrayObj.forEach(personObj => {
  console.log(personObj.personal.name,personObj.company.name);
});

```

## ドット記法とブランケット記法

今まで何の説明もなく以下のようなコードでオブジェクトの中身を出力していたと思います。

```jsx
const person = {name: "Jane", age: "24"}
console.log(person.name,person.age)
```

このように、オブジェクトのプロパティを取得する方法を**ドット記法と言います。**

また、一般的には使われませんがブランケット記法というのもあります。記述の単純さでドット記法に劣るため、あまり使われませんが一応紹介しておきます。

## **prototype**というオブジェクト
prototypeをご存知ですか？
まずは簡単な例を挙げます。
```jsx
const myArray = new Array('foo','var')
console.log(myArray.join());
```
上の例では、Array()コンストラクタ関数を使用して配列を生成し、join()メソッドを呼び出しています。

ここで疑問が出ます。joinメソッドはmyArrayインスタンスで定義されていないのに、あたかもjoinメソッドがすでに定義されているかのようにアクセスできてますよね。

これ、なぜアクセスできるのかというと、**プロトタイプチェーン**を辿って発見したArray()コンストラクタの**prototypeプロパティ**が持つ**prototypeオブジェクト**にあるjoinメソッドを呼び出しているからです。

### protptypeオブジェクトとは
全てのオブジェクトは必ずprototypeプロパティを継承しています。例えば、以下のコードを出力し、プロパティを確認してみてください。
```jsx
const obj = {
    name: "jone"
}
console.log(obj)
```
よく見ると、prototypeというプロパティがあるのを確認できますね。その中身を覗いて見るとjoinメソッドがあるのを確認できます。
myArray.join()というのは、myArray.prototype.join()を呼び出しているのと同じ意味を持っているという事です。
以下のコードを出力してみると、trueが帰ってくるのがわかります。
```jsx
const myArray = new Array('foo','var')
console.log(myArray.join === myArray.prototype.join);
```
### プロトタイプチェーンとは
> 生成されたインスタンスオブジェクトからコンストラクタ関数を参照できるリンクが提供されます。この時、コンストラクタ関数自身があるコンストラクタを持っている場合にはさらに遡るリンクが発生し、通常はprototypeに遡るまで連鎖します。このことをプロトタイプチェーンと言います。

どういうこっちゃという話ですが、要はmyArray.join()とメソッドを呼び出した際、まずはmyArrayオブジェクト自身にjoinメソッドがあるかを検索して、無ければ最終的にprototypeプロパティまでjoin()メソッドがないかを探しにいく、ということですね。


## 最後に
prototypeはそこまで突っ込んで調べた事がなかったので、本書はそういう本質的なところを知れるので、今まで使っていたオブジェクトについての理解度がかなり上がりました。
基礎的なところを学ぶのは短期的には成果が出ないかもしれませんが、フロントエンドの技術の移り変わりが激しい中で自分がついていくには基礎的なところを知っておくことで、新しいフレームワーク等出てもキャッチアップのスピードは上がるのではないかなと思っております。