JavaScript入門 その8：新しい構文、エラー

JavaScript入門の書籍を読んで書いてあったこと＋自分で調べたことのメモ書きその8。新しい構文、エラー。


# 新しい構文

#### 分割代入
分割代入は角カッコ内に変数を列挙して複数の変数にまとめて代入ができる。

```js
let [a, b, c] = ["one", "two", "three"];
console.log(a, b, c);
```

【実行結果】
```console
one two three
```

#### スプレッド構文
スプレッド構文はドット3つで配列や文字列などの反復可能なオブジェクトを複数の値に展開する。

例：arr1 と arr2 の内容は同じになる。

```js
let arr1 = ["a", "b", "c"];
let arr2 = [...arr1];
console.log(arr1);
console.log(arr2);
```

【実行結果】
```console
['a', 'b', 'c']
['a', 'b', 'c']
```

例：関数に引数を渡す時に使用する。

```js
let testFunc = (x, y) => {
   x + y;
};

let arr = [-10, 100];

console.log(testFunc(...arr));
```

【実行結果】
```console
90
```

例：配列を連結する。

```js
let arr1 = [0, 1, 2];
let arr2 = [3, 4, 5];
let arr3 = [...arr1, ...arr2];
console.log(arr3);
```

【実行結果】
```console
[0, 1, 2, 3, 4, 5]
```

#### 拡張オブジェクトリテラルのプロパティ
拡張オブジェクトリテラルのプロパティについて、下記のような記述ができる。

* 角カッコで囲んだ式の結果をプロパティにすることができる。
* プロパティ名と同じ変数の値をプロパティの値にする場合 `name:name` を `name` だけの短縮表記にできる。

```js
let propertyName = "section";
let url = "https://example.com";

let obj = {
  [propertyName + 1]: 'abc',
  [propertyName + 2]: 'def',
  url,
};

console.log(obj);
```

【実行結果】
```console
{section1: 'abc', section2: 'def', url: 'https://example.com'}
```

#### オプショナルチェーン演算子
ES2020で追加された。
オプショナルチェーン演算子 `?.` は左辺が null か undefined の場合はそこで undefined を返す。nullでもundefinedでもない場合はそのまま右のメンバーにアクセスする。
関数、メソッドの呼び出しにも使用できる。`method?.()` は呼び出そうとした関数、メソッドがない場合は undefined を返す。

```js
let obj = {};
console.log(obj.propA?.xxx);
```

【実行結果】
```console
undefined
```

#### Null合体演算子
ES2020で追加された。
Null合体演算子 `??` は左辺が null か undefined の場合は右辺の値を、それ以外の場合は左辺の値を返す。

```js
let testFunc = () => {
  return undefined;
}
let result = testFunc() ?? "Null or Undefined";
console.log(result);
```

【実行結果】
```console
Null or Undefined
```


# エラーの種類

#### ReferenceError
存在しない変数を参照された場合に発生する。

```js
console.log(obj);
```

【エラーメッセージ】
```console
Uncaught ReferenceError: obj is not defined
    at スクリプト スニペット #1:1:13
```

未定義の変数のプロパティを参照したりメソッドを呼んだ場合も同様。
```js
console.log(obj.abc);
```

【エラーメッセージ】
```console
Uncaught ReferenceError: obj is not defined
    at スクリプト スニペット #1:1:13
```

#### TypeError
値が期待された型ではなかった時などに発生する。

変数の定義だけをして未初期化の場合（値が undefined の場合）、その変数のプロパティを参照すると TypeError となる。メソッドを呼び出した場合も同様。
変数の値が undefined なのでそのプロパティはないので読めない。

```js
let obj;
console.log(obj.abc);
```

【エラーメッセージ】
```console
Uncaught TypeError: Cannot read properties of undefined (reading 'abc')
    at スクリプト スニペット #1:2:17
```

変数にオブジェクトリテラルを代入し未定義のメソッドを呼んだ場合は TypeError となるが、前の例とはエラーメッセージが異なる。
obj.xyz は未定義で undefined であり関数型ではないので TypeError が発生するということだと思われる。

```js
let obj = {};
console.log(obj.xyz());
```

【エラーメッセージ】
```console
Uncaught TypeError: obj.xyz is not a function
    at スクリプト スニペット #1:2:17
```

未定義のメソッドの呼び出しではなく未定義のプロパティの参照の場合は undefined が返ってくる。エラーは発生しない。

```js
let obj = {};
console.log(obj.abc);
```

【実行結果】
```console
undefined
```


# 参考情報

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

### WEBページ
[ReferenceError - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/ReferenceError)
[TypeError - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/TypeError)