JavaScript気になる構文まとめメモ

# はじめに

他の人が書いたJavaScriptのコードを読む機会があり「この構文ってどういう意味？」「この構文の呼び名は？」となることがあったので、調べたついでに気になった構文をまとめました。

自分用のメモとして簡易に記述しているので、厳密な定義を知りたい方は最後の参考サイトをご覧ください。

# 真と偽：truthy, falsy

構文まとめの前に、構文の中に式がたくさん出てくるので、真になる値と偽になる値を軽く整理しておきます。

## 真になる値：truthy

```javascript
// true
console.log(Boolean(true)); // true

// ゼロでない数値
console.log(Boolean(10)); // true
console.log(Boolean(-20)); // true

// 空でない文字列
console.log(Boolean("Hello")); // true

// オブジェクトなどの参照
console.log(Boolean({})); // true
console.log(Boolean([])); // true
console.log(Boolean(new Date())); // true
console.log(Boolean(function(){})); // true
```

## 偽になる値：falsy

```javascript
// false
console.log(Boolean(false)); // false

// ゼロ
console.log(Boolean(0)); // false

// 空文字
console.log(Boolean("")); // false

// nullなど
console.log(Boolean(null)); // false
console.log(Boolean(undefined)); // false
console.log(Boolean(NaN)); // false
```

# 代入系

## Null 合体代入 (??=)

### 構文

```
変数 ??= 式
```

### 説明

変数がnullまたはundefinedでない場合、変数の値は変わりません。
変数がnullまたはundefinedの場合、式の値が変数に代入されます。

### サンプル

```javascript
let a = 0;

a = 123;
a ??= 456;
console.log(a);
// 123

a = null;
a ??= 456;
console.log(a);
// 456
```

## 論理積代入 (&&=)

### 構文

```
変数 &&= 式
```

### 説明

変数の評価が真の場合、式の値が変数に代入されます。

### サンプル

```javascript
let a = 0;

a = true;
a &&= 123;
console.log(a);
// 123

a = false;
a &&= 123;
console.log(a);
// false

a = null;
a &&= 123;
console.log(a);
// null

a = 10;
a &&= 123;
console.log(a);
// 123
```

## 論理和代入 (||=)

### 構文

```
変数 ||= 式
```

### 説明

変数の評価が偽の場合、式の値が変数に代入されます。

### サンプル

```javascript
let a = 0;

a = true;
a ||= 123;
console.log(a);
// true

a = false;
a ||= 123;
console.log(a);
// 123

a = null;
a ||= 123;
console.log(a);
// 123

a = 10;
a ||= 123;
console.log(a);
// 10
```

## 配列：分割代入

### 構文（一部抜粋）

```
const [変数1, 変数2] = 配列;

const [変数1, , 変数2] = 配列;
```

### 説明

配列から要素を取り出して、変数1、変数2に代入します。
間を飛ばすこともできます。

### サンプル

```javascript
let array = [100, 200, 300];

const [a1, a2] = array;
console.log(a1, a2);
// 100 200

const [b1, ,b3] = array;
console.log(b1, b3);
// 100 300
```

## オブジェクト：分割代入

### 構文（一部抜粋）

```
const {変数1, 変数2} = オブジェクト;

const { a: 変数1, b: 変数2 } = オブジェクト;
```

### 説明

オブジェクトからプロパティを取り出して、変数1、変数2に代入します。

### サンプル

```javascript
let obj = {id: 100, name: 'test', value: 'abc'};

const {id, name} = obj;
console.log(id, name);
// 100 "test"

const {id: i, name: n} = obj;
console.log(i, n);
// 100 "test"
```

## 残余プロパティ

### 構文

```
const {変数1, ...オブジェクト2} = オブジェクト1;
```

### 説明

変数1と名前が一致するオブジェクト1のプロパティをオブジェクト1から変数1へ代入します。
変数1と名前が一致しなかったオブジェクト1の残りのプロパティをオブジェクト2へ代入する。

### サンプル

```javascript
let obj = {id: 100, name: 'test', value: 'abc'};

const {id, ...other} = obj;

console.log(id);
// 100

console.log(other);
// {
//   "name": "test",
//   "value": "abc"
// }
```

# 演算子系

## Null合体演算子

### 構文

```
式1 ?? 式2;
```

### 説明

式1がnullまたはundefinedでない場合、式1の値を返します。
式1がnullまたはundefinedの場合、式2の値を返します。

### サンプル

```javascript
x = null ?? 123;
console.log(x);
// 123

x = 999 ?? 123;
console.log(x);
// 999
```

## カンマ演算子

### 構文

```
(式1, 式2, 式n)
```

### 説明

式がカンマで列挙されているとき、最も右側の式の値を返します。

### サンプル

```javascript
x = (1, null, "abc");

console.log(x);
// "abc"
```

## 三項演算子

### 構文

```
条件式 ? 真の時の式 : 偽の時の式
```

### 説明

条件式が真の場合、真の時の式を返します。
条件式が偽の場合、偽の時の式を返します。

### サンプル

```javascript
let greeting;

greeting = "hello"
const x = greeting == "hello" ? "こんにちは" : "その他" ;
console.log(x);
// "こんにちは"

greeting = "goodbye"
const y = greeting == "hello" ? "こんにちは" : "その他" ;
console.log(y);
// "その他"
```

# 引数系

## デフォルト引数

### 構文

```
function 関数名(引数1 = デフォルトの値1, ..., 引数N = デフォルトの値N)
```

### 説明

引数に値が指定されなかった場合、デフォルトの値が引数に設定されます。

### サンプル

```javascript
function fnName(p1 = 10, p2 = "abc") {
  console.log(p1, p2);
}

fnName();
// 10 "abc"

fnName(20, "xyz");
// 20 "xyz"

fnName(100);
// 100 "abc"

fnName(p2 = "zzz");　 // 引数を指定できるわけではない
// "zzz" "abc"

fnName(undefined, "zzz");　
// 10 "zzz"

fnName(null, "zzz");　
// null "zzz"
```

## スプレッド構文

### 構文1

```
関数(...配列)
```

### 説明

配列の参照を渡すのではなく、配列の要素をすべて並べて引数に渡します。

### サンプル

```javascript
// 関数(...配列)
const array = [1, 2, 3, 4, 5];

function fnName(a, b, c, d, e) {
  console.log(a, b, c, d, e);
}

fnName(...array);
// 1 2 3 4 5

fnName(array);
// [1,2,3,4,5] undefined undefined undefined undefined
// 一つ目の引数に配列が丸ごと入っている
```

### 構文2

```
配列1[...配列2]
```

### サンプル

```javascript
// 配列1[...配列2]
const array1 = [1, 2, 3, 4, 5];

console.log("スプレッド構文を使った例")
const array2 = [...array1];
console.log(array2); // [1, 2, 3, 4, 5]

array2.pop(); //最後の要素を削除
console.log(array2); // [1, 2, 3, 4]
console.log(array1); // [1, 2, 3, 4, 5] 元の配列は変化なし

console.log("スプレッド構文を使わない例")
const array3 = array1;
console.log(array3); // [1, 2, 3, 4, 5] 結果は同じだが

array3.pop(); //最後の要素を削除
console.log(array3); // [1, 2, 3, 4]
console.log(array1); // [1, 2, 3, 4] 元の配列も減ってる
```

### 構文3

```
new オブジェクト(...配列)
```

### サンプル

```javascript
class Obj {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
};

array = [123, 456];

obj = new Obj(...array);

console.log(obj);
// {
//   "height": 123,
//   "width": 456
// }
```

## 残余引数

### 構文

```
function 関数名(変数1, 変数2, ...変数A) {
```

### 説明

可変長引数
関数が不定数の引数を配列として受け入れることができ

### サンプル

```javascript
function fnName(p1, p2, p3, p4, p5) {
  console.log(p1, p2, p3, p4, p5);
}

array = [3, 4, 5];

fnName(1, 2, ...array);
// 1 2 3 4 5
```

# プロパティ系

## オプショナルチェイニング
オプショナルチェーン

### 構文（一部抜粋）

```
オブジェクト.変数?.変数
オブジェクト.変数?.[式]
オブジェクト.配列?.[インデックス]
オブジェクト.関数?.(引数)

obj.val?.prop;
obj.val?.[expr];
obj.arr?.[index];
obj.func?.(args);
```

### 説明

オブジェクトの途中で、undefineやnullがあっても例外が発生しない

### サンプル

```javascript
const rect = {height: 10, width: 20};
const obj = {id: 123, name: "test", size: null}; // まだsizeにrectを設定していない

console.log(obj.name);
// console.log(obj.size.height); // Cannot read properties of null エラーになる

console.log(obj.size?.height);
// undefined
```

## プロパティアクセサー

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

```javascript
const rect = {height: 10, width: 20};

console.log(rect.height);     // ドット表記 10
console.log(rect['height']);  // ブラケット表記 10
```

# その他

## テンプレートリテラル (テンプレート文字列)

### 構文
```
`文字列 ${式}`
```

### 説明

バッククォートで囲む。
${式}を書くと、中の式が文字列に展開される。

### サンプル
```javascript
console.log(`計算結果、${1+1}`); 
// "計算結果、2"
```

## タグ付きテンプレート

### 構文
```
タグ名`文字列 ＄(式)`
```

### 説明
関数を用意しておく。
タグ名として用意しておいたタグを指定する。
続けてテンプレートリテラルを書く。

### サンプル
```javascript
function highlight(strings, ...values) {
  result = '';
  strings.forEach((string, i) => {
    console.log(string, i, values[i]);
    result += string
    result += values[i] ? `<strong>${values[i]}</strong>` : '';
    console.log(result);
  }); 
  return result;
}

const message = highlight`私の名前は${"テスト太郎"}です。年齢は${6}歳です。`;
console.log(message);
```

### コンソール出力
```
"私の名前は" 0 "テスト太郎"
"私の名前は<strong>テスト太郎</strong>"
"です。年齢は" 1 6
"私の名前は<strong>テスト太郎</strong>です。年齢は<strong>6</strong>"
"歳です。" 2 undefined
"私の名前は<strong>テスト太郎</strong>です。年齢は<strong>6</strong>歳です。"
"私の名前は<strong>テスト太郎</strong>です。年齢は<strong>6</strong>歳です。"
```

# 参考

### 書籍
「これからはじめるReact実践入門 コンポーネントの基本からNext.jsによるアプリ開発まで」
山田 祥寛 (著)

### Webサイト
MDN Web Docs

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators


# 最後に
MDNのサンプルコードを読むだけでは理解しづらかったですが、サンプルコードを書いてみることで理解が深まりました。
書籍やWebサイトを読むだけでなく、自分でサンプルコードを書いてみることをオススメします。