JavaScriptをよりスマートに書くための構文チートシート

## 数値

### 指数
`BeN`と書くことで$B\times10^N$を表すことができる。
```javascript
6.02e23  // 6.02 * 10 ** 23
314e-2  // 3.14
```

### 区切り文字
`1234567890`を表すのに我々は通常区切り文字`,`を用いて`1,234,567,890`と表すが、JavaScriptでは`_`を区切り文字として用いる。
```javascript
1_234_567_890
```

### n進数
n進数は先頭に以下の識別子をつけることで表す。ただし10進数では、`012`のように`0`を先頭につけることはできない（8進数とみなされるため）。

| n | 2 | 8 | 10 | 16 |
|:-:|:-:|:-:|:--:|:--:|
|識別子|`0b`|`0o`|なし|`0x`|

```javascript
0b0011
0o3752
314  // `0314`はエラー
0xDF2A
```


## 型変換

### 理論値にする
`!!`を付けることで、`Truthy`なら`true`に、`Falsy`なら`false`に変換される。
```javascript
!!{}, !![], !!Infinity, !!1, !!"0"  // true
!!null, !!undefined, !!NaN, !!0, !!""  // false
```
また`!`を付けることで、`Falsy`なら`true`に、`Truthy`なら`false`に変換される。
```javascript
!null, !undefined, !NaN, !0, !""  // true
!{}, ![], !Infinity, !1, !"0"  // false
```

### 数値にする
`+`を付けることで、文字列などが数値型に変換される。
```javascript
+"1", +true  // 1
+"0", +"", +false, +null,  +[]  // 0
+"a", +undefined, +{}  // NaN
+"Infinity"  // Infinity
```

### 文字列にする
`""+`や`` `${......}` ``をつけることで、数字や配列などが文字列型に変換される。
```javascript
""+123  // "123"
`${true}`  // "true"
```


## 式と演算子

### テンプレートリテラル
`` ` ` ``で挟まれたテンプレートリテラル内では、`${...}`として式を使える。
```javascript
i = `Hello, ${name}!
Nice to meet you!`;
// i = 'Hello, ' + name + '!\nNice to meet you!';
```
またテンプレートリテラルについて、タグを使うことができる。
```javascript
const func = (list, ...values) => (`${list} : ${values}`);
console.log(func`${1}+${2}-${3}`);  // ',+,-, : 1,2,3'
```

### 代入演算子
```javascript
a += b;
// a = a + b;
a -= b;
// a = a - b;
a *= b;
// a = a * b;
a /= b;
// a = a / b;
a %= b;
// a = a % b;
a **= b;
// a = a ** b;
```

### インクリメント・デクリメント
インクリメント`++`やデクリメント`--`を変数の前に置いた場合と後に置いた場合では挙動が異なる。
- 前に置いた場合
**インクリメント**あるいは**デクリメント** → **代入処理**（`initial + 1` or `initial - 1`）
- 後に置いた場合
**代入処理**（`initial`） → **インクリメント**あるいは**デクリメント**
```javascript
i = ++a;
// a += 1; i = a;
i = a++;
// i = a; a += 1;
i = --a;
// a -= 1; i = a;
i = a--;
// i = a; a -= 1;
```

### 三項演算子
これを利用すると、`if ... else ...`構文を一行で書くことができる。
```javascript
i = c ? t : f;
// if (c) {i = t} else {i = f};
i = c1 ? t1 : c2 ? t2 : ...... : f;
// if (c1) {i = t1} else if (c2) {i = t2} else if ...... else {i = f};
```

### AND演算子
`&&`は「**最初に見つけた`falsy`な値**」あるいは「(全値が`truthy`の場合)**最後の値**」を返却する。
返却値を見つけるまで、**左から順に**値を評価する。
```javascript
i = a && b;
// i = a ? b : a;
a &&= b;
// if (a) {a = b};
```

### OR演算子
`||`は「**最初に見つけた`truthy`な値**」あるいは「(全値が`falsy`の場合)**最後の値**」を返却する。
返却値を見つけるまで、**左から順に**値を評価する。
```javascript
i = a || b;
// a = !a ? b : a;
a ||= b;
// if (!a) {a = b};
```

### NULL合体演算子
`??`は「**最初に見つけた`null|undefined`でない値**」あるいは「(全値が`null|undefined`の場合)**最後の値**」を返却する。
返却値を見つけるまで、**左から順に**値を評価する。
```javascript
i = a ?? b;
// i = (a === null || a === undefined) ? b : a;
a ??= b;
// if (a === null || a === undefined) {a = b};
```

### カンマ演算子
それまでの値にかかわらず「**最後の値**」を返却する。
**左から順にすべて**の値を評価する。
```javascript
i = (a, b, c);
// a; b; i = c;
```

### 分割代入
```javascript
[ia, , ic, ...ir] = [a, b, c, d, e];
// ia = a; ic = c; ir = [d, e]
{a: ia, b: ib, ...ir} = {a: 3, b: 1, c: 4, d: 1, e: 5}
// ia = 3; ib = 1; ir = {c: 4, d: 1, e: 5}; 
```
#### 変数の入れ替え
上の分割代入を応用すると、変数`a`と変数`b`の中身を入れ替えることができる。
```javascript
[a, b] = [b, a];
// c = [b, a]; [a, b] = c;
```
#### スプレッド
（連想）配列の要素を分割して返す。
```javascript
...list;
...obj;
```

### 正の剰余
JavaScriptでは通常、負数の剰余（`%`）は負となるが、非負にしたい場合は次の`mod`関数を定義して用いるとよい。
```javascript
var mod = (m, n) => (m % n < 0 ? m % n + (n < 0 ? -n : n) : m % n) + 0;

console.log(5 % 2, -5 % 2, 5 % -2, -5 % -2);  // 1, -1, 1, -1
console.log(mod(5, 2), mod(-5, 2), mod(5, -2), mod(-5, -2));  // 1, 1, 1, 1
```


## 文

### while文
```javascript
while (condition) {
    // If this condition is falsy at first,
    // these lines will not be executed.
}

do {
    // Even if this condition is falsy at first,
    // these lines will be executed at least once.
} while (condition)
```
#### 代入式を条件に用いる
以下の例では、`ret`を得られる（あるいは`list.shift()`できる）限り反復する。
```javascript
const list = [3, 1, 4, 1, 5];
let ret;
while ((ret = list.shift())) console.log(ret);  // 3, 1, 4, 1, 5
```

### for文
```javascript
for (let i = 0; i <= 2; i++;) console.log(i);  // 0, 1, 2
for (const val of [3, 1, 4]) console.log(val);  // 3, 1, 4
for (const key in [3, 1, 4]) console.log(key);  // "0", "1", "2"
```
#### 非同期反復オブジェクトに対するfor-of文
```javascript
for await (const file of zip) console.log(file);
```

### switch文
```javascript
switch (n) {
    case 1:
        // n === 1
        break;
    case 2:
        // n === 2
    case 3:
        // n === 2 || n === 3
        break;
    default:
        // Other values
        break;
}
```
#### switch文でif文を表す
```javascript
switch (true) {
    case condition1:
        // if (condition1)
        break;
    case condition2:
        // else if (condition2)
        break;
    default:
        // else
        break;
}
```

### ラベル
```javascript
myFor: for (const i in [0, 1, 2]) {
    console.log(i);  // 0, 1
    if (i) break myFor;
}

myLabel: {
    console.log('O');
    break myLabel;
    coonsole.log('X');
}
```

### エラーハンドリング
```javascript
try {
    writeFile();
} catch (error) {
    throw new Error('MyError');
} finally {
    closeFile();
}
```


## 関数

### 関数宣言
`function`により宣言された関数は、宣言より前でも巻き上げて使うことができる。また、コンストラクターやメソッドとしても利用できる。
```javascript
function increment(e = 1) {  // デフォルト引数
    return ++e;
}
```

### アロー関数
```javascript
var increment = e => ++e;

var error = () => throw new Error(0);  // 引数がない場合は`()`が必要

var incArray = async (e) => {  // 引数があっても`()`を使える
    for (i of e) i++;
    return ret;
}
```

### 即時実行関数式
関数がメモリを使用せずに実行され、返却値は破棄される。
```javascript
(function foo() {
    console.log('foo');
})();
```


## 配列

配列そのものを書き換えるメソッドは **※** で示している。

### 値の参照
#### 最後からn番目の値
```javascript
list.at(-n)
```
#### 要素の検索
```javascript
list.includes(item, start)  // true or false
```
#### 番号の検索
```javascript
// 最初から検索
list.index(value, start)
// 最後から検索
list.lastIndex(value, start)
```

### 配列を文字列化
単純に文字列リテラルに変換する。型変換でも同様に可能。
```javascript
list.toString()
```
`separator`で配列の各要素を連結して一つの文字列にする。`separator`の初期値は`","`。
```javascript
list.join(separator)
```

### 操作した配列
#### 一部を取り出した配列
```javascript
list.slice(start, end)
```
#### 値を置換した配列
`list.at()`のように負値も使える。
```javascript
list.with(index, value)
```
#### ソートした配列
```javascript
const compare = (a, b) => a - b;
list.toSorted(compare)
```
#### 値を反転した配列
```javascript
list.toReversed()
```
#### 配列の連結
```javascript
list1.concat(list2[, list3, ......])
```
#### 配列の平坦化
```javascript
list.flat(n)  // n階層まで平坦化
list.flat(Infinite)  // 全て平坦化

list.flatMap(condition)
// list.map(condition).flat(1)
```

### 配列の書き換え※
#### 値の追加※
```javascript
// 最初に追加
const length = list.unshift(...values);
// 最後に追加
const length = list.push(...values);
```
#### 値の削除※
```javascript
// 最初から削除
const first = list.shift();
// 最後から削除
const last = list.pop();
```
#### 値の変更※
```javascript
list.splice(start, length, ...values)
```
#### 値のフィル※
```javascript
list.fill(value, start, end);
```
#### 配列のソート※
```javascript
const compare = (a, b) => a - b;
list.sort(compare);
```
#### 値の反転※
```javascript
list.reverse();
```
#### 値のコピペ※
```javascript
list.copyWithin(pasteStart, copyStart, copyEnd);
```

### forEach系
#### 各要素に対する処理
```javascript
list.forEach((item[, index, array]) => /* 処理 */)
```
#### 要素の検証
```javascript
// 全ての要素が条件を満たすか
console.log(list.every((item[, index, array]) => /* 条件 */));
// いずれかの要素が条件を満たすか
console.log(list.some((item[, index, array]) => /* 条件 */));
```
#### 条件を満たす値・番号
```javascript
// 最初から検索・値を返却
list.find((item[, index, array]) => /* 条件 */)
// 最初から検索・番号を返却
list.findIndex((item[, index, array]) => /* 条件 */)
// 最後から検索・値を返却
list.findLast((item[, index, array]) => /* 条件 */)
// 最後から検索・番号を返却
list.findLastIndex((item[, index, array]) => /* 条件 */)
```
#### 条件でフィルターした配列
```javascript
console.log(list.filter((item[, index, array]) => /* 条件 */))
```
#### 各要素を加工した配列
```javascript
list.map((item[, index, array]) => /* 加工値 */)
```
#### 各要素を計算
`ret`に対する操作を繰り返し、ループ終了時の`ret`を返却する。`ret`の初期値は`defRet`。
```javascript
// 最初から順に
list.reduce((ret, value[, index, array]) => /* 操作 */[, defRet])
// 最後から順に
list.reduceRight((ret, value[, index, array]) => /* 操作 */[, defRet])
```

### オプショナルチェーン（連想配列）
連想配列で安全に特定オブジェクトへアクセスする。
```javascript
obj?.dog?.name
```


## ビット演算

### ビット演算子
#### AND演算子
`a & b`は、`a`と`b`の両方が`1`であるビットに対し`1`を、それ以外に対し`0`を返します。

| `a & b` | `1` | `0` | `0` | `0` |
|:-------:|:---:|:---:|:---:|:---:|
|   `a`   | `1` | `1` | `0` | `0` |
|   `b`   | `1` | `0` | `1` | `0` |

```javascript
0b1100 & 0b1010  // 0b1000
a &= b;  // a = a & b;
```
#### OR演算子
`a & b`は、`a`と`b`の両方か片方が`1`であるビットに対し`1`を、それ以外に対し`0`を返します。

| `a \| b` | `1` | `1` | `1` | `0` |
|:--------:|:---:|:---:|:---:|:---:|
|    `a`   | `1` | `1` | `0` | `0` |
|    `b`   | `1` | `0` | `1` | `0` |

```javascript
0b1100 | 0b1010  // 0b1110
a |= b;  // a = a | b;
```
#### XOR演算子
`a ^ b`は、`a`と`b`の片方のみが`1`であるビットに対し`1`を、それ以外に対し`0`を返します。

| `a ^ b` | `0` | `1` | `1` | `0` |
|:-------:|:---:|:---:|:---:|:---:|
|   `a`   | `1` | `1` | `0` | `0` |
|   `b`   | `1` | `0` | `1` | `0` |

```javascript
0b1100 ^ 0b1010  // 0b1110
a ^= b;  // a = a ^ b;
```
#### NOT演算子
`~a`は、`a`のビットを反転して返します。
```javascript
   ~0b00000000000000000000000000101010
//  0b11111111111111111111111111010101
```

### ビットシフト演算子
```javascript
    0b00000000000000000000000000101010 << 2
//  0b00000000000000000000000010101000
    0b11111111111111111111111111010101 << 2
//  0b11111111111111111111111101010000

    0b00000000000000000000000000101010 >> 2
//  0b00000000000000000000000000001010
    0b11111111111111111111111111010101 >> 2
//  0b11111111111111111111111111110101 負

    0b00000000000000000000000000101010 >>> 2
//  0b00000000000000000000000000001010
    0b11111111111111111111111111010101 >>> 2
//  0b00111111111111111111111111110101 正


a <<= b;  // a = a << b;
a >>= b;  // a = a >> b;
a >>>= b;  //  a = a >>> b;
```

### フラグ管理
```javascript
let flags = 0b1010;
const FlagA = 1 << 0;  // 0001
const FlagB = 1 << 1;  // 0010

// フラグを立てる
flags |= FlagA;  // 1011

// フラグを消す
flags &= ~FlagB;  // 1001

// フラグを確認
console.log(!!(flags & FlagA));  // true
```