【JavaScript】ちょいムズ用語＆テクニックまとめ

docsや書籍で書かれていたことをメモしています
間違いがあればコメント頂けますと幸いです

# 変数編
### 宣言と代入
* `var`はもう使わない

||`const`|`let`|~~`var`~~|
|-|-|-|-|
|再宣言|不可|不可|可能|
|再代入|不可|可能|可能|

* 再宣言
```javascript
const a = 1
const a = 2 // Error

let b = 1
let b = 2 // Error
```

* 再代入
```javascript
const a = 1
a = 2 // Error

let b = 1
b = 1 // OK
```

* 複数の宣言も可能
```javascript
const a = 1, b = 2, c = 3

let d = 1, e = 2, f = 3
```

### プリミティブ型
* `const`で宣言したとき、その変数は変更不可（**イミュータブル**）
* `typeof`演算子で確認可能（`null`は`=== null`でしか確認できない）

:::note alert
`typeof`と類似している`instanceof`というのがあるが、`instanceof`はラッパーオブジェクトを検出する演算子なので注意
```javascript
const literal_a = "これはテキストです"
const wrapper_a = new String("これはテキストです")

literal_a instanceof String // false
wrapper_a instanceof String // true
```
:::

|例：|typeofの返値|ラッパー|
|-|-|-|
|Null|`"object"`|なし|
|Undefined|`"undefined"`|なし|
|理論型|`"boolean"`|`Boolean()`|
|数値型|`"number"`|`Number()`|
|長整数型|`"bigint"`|`BigInt()`|
|文字列型|`"string"`|`String()`|
|シンボル型|`"symbol"`|`Symbol()`|

### オブジェクト型
* `const`で宣言しても、プロパティであれば変更可能（**ミュータブル**）
* `typeof`演算子を使ってもほとんどの返値が`"object"`


|例：|typeofの返値|ラッパー|
|-|-|-|
|オブジェクト|"object"|`Object()`|
|配列|`"object"`|`Array()`|
|...|...|...|

### 分割代入
* `array`の要素や`object`のプロパティから個別に変数へ代入可能

* 配列の場合は`[]`内に宣言したい変数名を指定することで代入可能
* 配列の長さを超過する変数はすべて`undefined`となる
```javascript
const arr = [1, 2]

const [ a, b ] = arr 
// a = 1, b = 2

const [ a, b, c, d ] = arr
// a = 1, b = 2, c = undefined, d = undefined
```

* オブジェクトの場合は`{}`内にプロパティを指定することで、**プロパティ名と同じ変数名で宣言**される
* プロパティと異なる変数名で宣言したい場合は`{プロパティ名: 変数名}`とすることで可能
* オブジェクトの長さを超過する変数、または存在しないプロパティはすべて`undefined`となる
```javascript
const obj = { a: 1, b: 2 }

const { a, b } = obj
// a = 1, b = 2

const { a: first, b: second } = obj
// first = 1, second = 2

const { a, c, d } = obj
// a = 1, c = undefined, d = undefined 
```
* 代入された変数が`undefined`となったときに適応されるデフォルト値を設定できる
* `null`のときは動作しないので注意

```javascript
const obj = { a: 1, b: undefined, c: null }
const { a, b = 2, c = 3 } = obj
// a = 1, b = 2, c = null
```


# 関数編
### 関数宣言
```javascript
function f(n) {
    return n + 1;
}
```

### 関数式
```javascript
const f = function(n) {
    return n + 1;
}
```

### アロー関数
関数式の省略記法
```javascript
const f = (n) => { 
    return n + 1 
};

const f = n => n + 1;
```

### 無名関数
* `a`は関数の名前ではなく、`変数名`
* `a`に入っているのは**関数名のない関数**
```javascript
const f = function (n) {
    return n + 1;
}

f.name // f

f(1) // 2
```

### 高層関数とコールバック関数
* 関数を引数にとる関数
* 引数になる関数を**コールバック関数**という
```javascript
const highFnc = (fnc, n) => {
    return fnc(n);
}

const callbackFunc = (n) => n + 1;

highFunc(callbackFunc, 2); // 3
```

### カリー化
* 複数の引数を取る関数を、一つの引数を取る関数に変換すること
* カリー化された関数の一部の引数を固定して新しい関数を作ることを**関数の部分適用**という
* 要するに関数が、関数の引数を使った関数を返す形をとる

```javascript
// カリー化前の関数
const nocurryFunc = (a, b, c) => a + b + c;
nocurryFunc(1,2,3) // 6


// カリー化
const curryFunc = (a) => {
    return (b) => {
        return (c) => {
            return a + b + c;
        }
    }
}

curryFunc(1)(2)(3); // 6


// レベルの高い記法
const highlevel_curryFunc = a => b => c => a + b + c;

highlevel_curryFunc(1)(2)(3); // 6
```

### レストパラメータ
* `...引数名`とすることで、それ以降の引数は引数名の`array`として扱われる
```javascript
const restparamFunc => (a, b, ...args) {
    console.log(a, b, args);
}

restparamFunc(1,2,3,4,5)

// 1 
// 2 
// [3, 4, 5]
```

* 分割代入でも使用可能
```javascript
const arr = [1, 2, 3, 4, 5]

const [ a, b, ...c ] = arr
// a = 1, b = 2, c = [3, 4, 5]
```

# ショートサーキット評価
* 変数には`truthy`な値と`falsy`な値が存在する
* `Boolean(変数)`で確認可能
* 以下代表的な`falsy`な値
    * `false`
    * `0`
    * `""`
    * `null`
    * `undefined`
    * `Nan`


* なにがいいのか
```javascript
// ショートサーキット評価なし
let result;

if (a === 0) {
    result = b;
} else {
    result = a;
}


// ショートサーキット評価あり
let result = a || b;
```

### OR演算子
```javascript
let result = a || b;
```
|出力値|右辺：`truthy`|右辺：`falsy`|
|-|-|-|
|左辺：`truthy`|左辺|`true`値|
|左辺：`falsy`|`true`値|右辺|

### AND演算子
```javascript
let result = a && b;
```
|出力値|右辺：`truthy`|右辺：`falsy`|
|-|-|-|
|左辺：`truthy`|右辺|`false`値|
|左辺：`falsy`|`false`値|左辺|


### オプショナルチェーン演算子
* オブジェクトのプロパティ参照で活用される
* 左辺が`null`または`undefined`なら`undefined`を返す(エラーを発生させない)

```javascript
const result = {};

result.a // undefined

result.a.b // TypeError

result.a?.b // undefined

// メソッドでも可能
result.a()?b() // undefined
```

### Null合体演算子
* 制約の弱いOR演算子
* `null`か`undefined`のときにしか評価しない
```javascript
let result = a ?? b;
```

|出力値|右辺：`truthy`|右辺：`null`か`undefined`|
|-|-|-|
|左辺：`truthty`|左辺|`true`値|
|左辺：`null`か`undefined`|`true`値|右辺|