【JS】予約語

# はじめに

学習ログ記事です。読んでくださる方、ぜひ揉んでください。
対戦よろしくお願いします。

ECMA Script 公式ドキュメントより、予約語（`ReservedWord`）について

https://tc39.es/ecma262/multipage/ecmascript-language-lexical-grammar.html#prod-ReservedWord:~:text=Syntax-,ReservedWord,-%3A%3A%20one%20of

# 予約語とは

変数・関数の命名に利用できない文字列のこと
例
```js
const a = 'a' // ok
const break = 'a' // ダメ（break は予約語）
function const // ダメ（const は予約語）
```
`const` が命名に利用できると問題が発生するので、いくつかの文字列が予約語として使用を禁止されています。
# 予約語一覧

予約語の一覧は先ほどのURLより

https://tc39.es/ecma262/multipage/ecmascript-language-lexical-grammar.html#prod-ReservedWord:~:text=Syntax-,ReservedWord,-%3A%3A%20one%20of

用法の説明はChatGPTに生成してもらいました。簡単なイメージを掴む用で、ファクトチェックはしていません。
## 通常の予約語

| 予約語          | 用法の説明                         |
| ------------ | ----------------------------- |
| `await`      | 非同期関数内でPromiseの結果を待つ ※only inside async functions and modules         |
| `break`      | ループや`switch`文から抜け出す           |
| `case`       | `switch`文の中で条件を指定する           |
| `catch`      | 例外が投げられた時に処理をキャッチする           |
| `class`      | クラスを宣言する                      |
| `const`      | 再代入不可能な定数を宣言する                |
| `continue`   | ループの次の反復へ進む                   |
| `debugger`   | デバッグ中に実行を一時停止する               |
| `default`    | `switch`文で条件に合致するものがない場合に実行する |
| `delete`     | オブジェクトのプロパティを削除する             |
| `do`         | `do...while`ループを制御する          |
| `else`       | `if`文の条件が偽の場合に実行する            |
| `enum`       | 予約されているがJavaScriptでは未使用       |
| `export`     | モジュールから値や関数をエクスポートする          |
| `extends`    | クラスが他のクラスを継承する                |
| `false`      | 論理値の偽（false）を表す               |
| `finally`    | 例外の有無に関わらず実行される処理を定義する        |
| `for`        | ループ処理を制御する                    |
| `function`   | 関数を宣言する                       |
| `if`         | 条件が真の場合に実行される                 |
| `import`     | モジュールから値や関数をインポートする           |
| `in`         | プロパティがオブジェクト内に存在するかを確認する      |
| `instanceof` | オブジェクトが特定のクラスのインスタンスかを判定する    |
| `new`        | 新しいインスタンスを生成する                |
| `null`       | null値を表す                      |
| `return`     | 関数から値を返す                      |
| `super`      | 親クラスのコンストラクタやメソッドを参照する        |
| `switch`     | 複数の条件分岐を管理する                  |
| `this`       | 現在のオブジェクトを参照する                |
| `throw`      | 例外を投げる                        |
| `true`       | 論理値の真（true）を表す                |
| `try`        | 例外が発生する可能性のあるコードブロックを試行する     |
| `typeof`     | 値の型を返す                        |
| `var`        | 変数を宣言する                       |
| `void`       | 式の結果を無視してundefinedを返す         |
| `while`      | 条件が真の間ループする                   |
| `with`       | スコープチェーンにオブジェクトを一時的に追加する      |
| `yield`      | ジェネレータ関数内で中断し値を外部に送出する        |
## `strict mode` のみの予約語

JSには `strict mode`（厳格モード）というものがあります。
これを有効にすると、予約語が追加されます（以下の語が命名に使えなくなる）。

※公式ドキュメントによる分類ではこのような分類になりますが、`let`のみ予約語の振る舞いをする場合があります。後述。

| 予約語          | 用法の説明                                         |
| ------------ | --------------------------------------------- |
| `let`        | ブロックスコープの変数を宣言する                              |
| `static`     | クラスの静的メソッドやプロパティを定義する                         |
| `implements` | クラスが特定のインターフェースを実装することを宣言する（使用されていないが予約されている） |
| `interface`  | インターフェースを定義する（使用されていないが予約されている）               |
| `package`    | コードをモジュールとしてグループ化する（使用されていないが予約されている）         |
| `private`    | クラスのプライベートメンバーを定義する（使用されていないが予約されている）         |
| `protected`  | クラスの保護されたメンバーを定義する（使用されていないが予約されている）          |
| `public`     | クラスの公開メンバーを定義する（使用されていないが予約されている）             |


## 予約語ではないもの

以下のものは予約語ではありません。
よって、関数・変数の命名に使用可能です。

| 用語       | 用法の説明                                      |
| -------- | ------------------------------------------ |
| `as`     | 型変換の際にエイリアス名を定義する（TypeScriptで使われる）         |
| `async`  | 非同期関数を定義する                                 |
| `from`   | モジュールの特定の部分をインポートする際に使用する                  |
| `get`    | オブジェクトのゲッター関数を定義する                         |
| `meta`   | import.metaはモジュールの情報を提供する（新しいJavaScript機能） |
| `of`     | for...ofループで使用され、反復可能オブジェクトの値をループする        |
| `set`    | オブジェクトのセッター関数を定義する                         |
| `target` | イベントのターゲットを指す（主にDOMで使用される）                 |
# 予約語 留意事項

## `await` / `yield`

この2種は特殊で、「特定のケース以外で使用可能」な予約語です。

例：命名 `yield` はジェネレーターの中でのみ使用不可
```js
// ジェネレーターの中では使用不可
function* iterate (i) {
  const yield = 0;
  yield i;
  yield i += 1;
}

const it = iterate(0);
console.log(it.next());

// SyntaxError: Unexpected identifier 'yield'
```

```js
// ジェネレーターの外では使用可能
const yield = 'yield!'
console.log(yield)

// 出力：`yield!`
```

## `let`

`var` / `const` / `let` のうち `let` のみ命名として使用可能です（`strict mode`では無い時）。
ただし、`let let`と`const let`はいずれの場合でも不可です。
```js
function let() {
  return 'function let!'
}

console.log(let()) //出力：'function let!'
```

```js
var let = 'var let!'
console.log(let) //出力：'var let!'
```
## `Math` / `Date` は予約されていない

```js
console.log(Math.max(1, 2, 3)) //出力：3
```
このように使用できる組み込みオブジェクト`Math`ですが・・・

予約語として保護されていないため、上書きが可能です。
```js
const Math = 'const Math!';
console.log(Math) //出力：'const Math!'
console.log(Math.max(1, 2, 3)) //TypeError: Math.max is not a function
```

`Date`も同様です。
万が一の上書きが起こり得ます。注意しないといけませんね。

# おわりに

予約語を学ぶこと、その言語を学ぶのにいいかもしれませんね。基礎的なキーワードがまとまっているので。

思ったよりも保護されていないキーワードが多くて驚きました。

さて、引き続きECMA Script ドキュメントを読んでいきます。
また記事を書く予定です。

# 参考

https://tc39.es/ecma262/multipage/strict-mode-of-ecmascript.html

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

https://tc39.es/ecma262/multipage/ecmascript-language-expressions.html#prod-BindingIdentifier

https://tc39.es/ecma262/multipage/ecmascript-language-lexical-grammar.html#prod-ReservedWord:~:text=Syntax-,ReservedWord,-%3A%3A%20one%20of

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Math/max