JavaScript入門 その5：オブジェクト

JavaScript入門の書籍を読んで書いてあったこと＋自分で調べたことのメモ書きその5。オブジェクト。


# オブジェクト

JavaScriptのオブジェクトはデータと機能の集合体である。変数はプロパティ、関数はメソッド呼ぶ。
MDNのJavaScriptのオブジェクトの解説には何の説明もなく突然「メンバー」という言葉が出てくるが、メンバーとはプロパティ、定数、メソッド、他には何があるかわからないがとにかくオブジェクトが持つすべてのものをデータや機能すべてを「メンバー」と呼んでいるのではないかと思う。
JavaScriptのオブジェクトは柔軟性が高く、既存のオブジェクトにプロパティやメソッドを追加することができる。

### オブジェクトの定義・作成の方法
オブジェクトを作成する方法は複数ある。
その場限りでデータをまとめたい場合はオブジェクトリテラルを、それ以外のケースではnew演算子とコンストラクタを使う方法でオブジェクトを作成するとよい。


#### オブジェクトリテラル
[以前の記事](https://qiita.com/y_ito/items/34527f5206b35e5325c7#%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%83%AA%E3%83%86%E3%83%A9%E3%83%AB)参照。

```js
let obj = {
  x: 0,
  y: 0
};
```

#### 関数ベース
コンストラクタを定義してnew演算子とコンストラクタでオブジェクトを作成する。

```js
function Point(x, y) {
  this.x = x;
  this.y = y;
}

let point = new Point(0, 0);
```

#### classキーワード
ES2015から導入されたオブジェクトの定義の方法。JavaやPHPに近い書き方。

```js
class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
}
let obj = new Point2(1, 2);
```


### 標準組み込みオブジェクト
JavaScriptに最初から用意されているオブジェクト。
主な標準組み込みオブジェクトを下記に示す。

| カテゴリ | オブジェクト |
|:-|:-|
| 特殊な値 | Infinity, NaN, undefined, globalThis |
| グローバル関数 | isNaN, parseFloat, parseInt, encodeURI, decodeURI など |
| 基本オブジェクト | Object, Function, Boolean, Symbol |
| エラーオブジェクト | Error, RangeError, ReferenceError, SyntaxError, TypeError など |
| 数値と日付 | Number（数値）, BigInt, Math, Date（日付） |
| テキスト処理 | String（文字列）, RegExp（正規表現） |
| 索引付きコレクション | Array（配列）など |
| キー付きコレクション | Map, Set など |
| 構造化データ | JSON など |
| 制御抽象化オブジェクト | Promise など |

WebブラウザやHTMLを操作する`DOM API`は標準組み込みオブジェクトではない。`DOM API`について後日。

### Dateオブジェクト
日時のオブジェクト。UTCの1970年1月1日からの経過ミリ秒数として日時を持つ。
日時を指定して作成した場合はローカル時刻を基に作成される。

```js
// new Date(year, monthIndex, day, hours, minutes, seconds)
// monthIndexは0オリジン。0は1月。
let day1 = new Date(1970, 0, 1, 0, 0, 0);
console.log(day1.getTime() + "msec");
console.log(day1.getTime() / 1000 / 60 / 60 + "h");
----------
【実行結果】
32400000msec
-9h
```

### プロパティ・メソッドの追加
`.プロパティ名` に値を代入することでプロパティを追加できる。

```js
let obj = {};
obj.firstName = "taro";
obj.lastName  = "yamada";
console.log(obj);
```

【実行結果】
```console
{firstName: 'taro', lastName: 'yamada'}
```

プロパティに関数オブジェクトを追加することでメソッドを追加できる。この際、関数（メソッド）オブジェクトはfunction式で定義する。アロー関数式は使用しない。
もし下記の例でアロー関数式を用いてメソッドを追加すると、function式の場合と異なりメソッド内で参照している `this` がメソッドが属しているオブジェクトではないのでおかしなことになる。

```js
obj.getFullName = function () {
  return `${this.firstName} ${this.lastName}`;
}
console.log(obj.getFullName());
```

【実行結果】
```console
taro yamada
```

### オブジェクトリテラル内ですべて定義する
`.プロパティ` で定義するのとオブジェクトリテラル内で `プロパティ: 値` で定義するのは同じことである。

```js
let obj = {
  firstName: "taro",
  lastName: "yamada",
  getFullName: function () {
    return `${this.firstName} ${this.lastName}`;
  }
}
console.log(obj);
console.log(obj.getFullName());
```

【実行結果】
```console
{firstName: 'taro', lastName: 'yamada', getFullName: ƒ}
taro yamada
```

ES2015より ***拡張オブジェクトリテラル*** が導入され下記のように :function を省略した記法でメソッドが定義できるようになった。

```js
let obj = {
  firstName: "taro",
  lastName: "yamada",
  getFullName() {
    return `${this.firstName} ${this.lastName}`;
  }
}
```

### 存在しないプロパティにアクセスした場合
オブジェクトに存在しないプロパティにアクセスした場合はエラーにならず、単に `undefined` が返されるだけで処理は続行される。

### 存在しないメソッドを呼んだ場合
プロパティの場合と異なり存在しないメソッドを呼ぶと TypeError が発生し処理は終了する。

```js
let obj = {}
console.log(obj.hoge1);
console.log("test1");
console.log(obj.hoge2());
console.log("test2");
```

【実行結果】
```console
test1
⇒エラーが発生する。
　Uncaught TypeError: obj.hoge2 is not a function
```


# 名前空間
`let`、`const` で変数、定数を定義すると、その定義がある名前空間（クラス、関数、メソッド、ブロック）がスコープとなる。
`var` で定義した変数はグローバルな名前空間に属する変数となる。

```js
let func = function () {
    {
        let aa = 1;
    }
    return aa;
}
console.log(func());
```

【実行結果】
```console
⇒エラーが発生する。
　Uncaught ReferenceError: aa is not defined
```


# プロトタイプベースのオブジェクト指向
JavaScriptはプロトタイプベースのオブジェクト指向言語である。JavaやRubyなど多くのオブジェクト指向言語はクラスベースのオブジェクト指向である。
プロトタイプベースではオブジェクトの設計図であるクラスは存在せず、原型となオブジェクトであるプロトタイプを参照してオブジェクトを生成する。


# 参考情報

### 書籍
[解きながら学ぶJavaScriptつみあげトレーニングブック | マイナビブックス](https://book.mynavi.jp/ec/products/detail/id=126984 "解きながら学ぶ JavaScriptつみあげトレーニングブック | マイナビブックス") 7章

### WEBページ
[JavaScript オブジェクトの基本 - ウェブ開発を学ぶ | MDN](https://developer.mozilla.org/ja/docs/Learn/JavaScript/Objects/Basics)
[JavaScript のプロトタイプベースについて[やまそうのブログ] | あしたのチームTechBlog](https://www.wantedly.com/companies/ashita-team/post_articles/298904)