プロミスの使用 - JavaScript

プロミスの使用
=======

* « 前のページ
* 次のページ »

プロミス (`Promise`) は、非同期処理の最終的な完了もしくは失敗を表すオブジェクトです。多くの人々は既存の用意されたプロミスを使うことになるため、このガイドでは、プロミスの作成方法の前に、関数が返すプロミスの使い方から説明します。

基本的に、プロミスはコールバックを関数に渡すかわりに、関数が返したオブジェクトに対してコールバックを登録するようにするというものです。 `createAudioFileAsync()` という非同期に音声ファイルを生成する関数を考えてみましょう。この関数は構成オブジェクトと 2 つのコールバック関数を受け取り、片方のコールバックは音声ファイルが無事作成されたときに呼び出され、もう一つはエラーが発生したときに呼び出されるとします。

以下のコードは `createAudioFileAsync()` を使用したものです。

```js
function successCallback(result) {
  console.log(`Audio file ready at URL: ${result}`);
}

function failureCallback(error) {
  console.error(`Error generating audio file: ${error}`);
}

createAudioFileAsync(audioSettings, successCallback, failureCallback);
```

`createAudioFileAsync()` をプロミスを返すように書き換えると、コールバックを次のように割り当てることができます。

```js
createAudioFileAsync(audioSettings).then(successCallback, failureCallback);
```

この記述方法にはいくつか利点があるので、順に説明します。

連鎖
--

よくあるニーズは、 2 つ以上の非同期処理を連続して実行することで、前回の処理が成功したときに、その結果をもとに後続の処理を始めることです。昔は、複数の非同期処理を連続して実行すると、古典的なコールバックピラミッドに陥っていました。

```js
doSomething(function (result) {
  doSomethingElse(result, function (newResult) {
    doThirdThing(newResult, function (finalResult) {
      console.log(`Got the final result: ${finalResult}`);
    }, failureCallback);
  }, failureCallback);
}, failureCallback);
```

プロミスでは、プロミス連鎖を作成することでこれを実現します。プロミスの API 設計では、コールバックは関数に渡されるのではなく、返されたプロミスオブジェクトに取り付けられるため、これは素晴らしいことです。

ここからがマジックです。 `then()` 関数は元とは異なる**新しいプロミス**を返します。

```js
const promise = doSomething();
const promise2 = promise.then(successCallback, failureCallback);
```

2 つ目のプロミス (`promise2`) は `doSomething()` の完了を表すだけではなく、渡した `successCallback` もしくは `failureCallback` の完了も表し、これらのコールバックはプロミスを返すまた別の非同期関数であっても構いません。その場合、`promise2` に追加されたコールバックはいずれもプロミスのキューにおいて、`successCallback` または `failureCallback` が返すプロミスの後ろに追加されます。

このパターンを使うと、より長い処理の連鎖を作成することができ、それぞれのプロミスは連鎖の中の非同期ステップの完了を表します。さらに、 `then` の引数はオプションで、`catch(failureCallback)` は `then(null, failureCallback)` の省略形です。エラー処理するコードがすべての手順で同じであれば、それをチェーンの終わりに付けることができます。

```js
doSomething()
  .then(function (result) {
    return doSomethingElse(result);
  })
  .then(function (newResult) {
    return doThirdThing(newResult);
  })
  .then(function (finalResult) {
    console.log(`Got the final result: ${finalResult}`);
  })
  .catch(failureCallback);
```

代わりにこれをアロー関数で表現しているのを見るかもしれません。

```js
doSomething()
  .then((result) => doSomethingElse(result))
  .then((newResult) => doThirdThing(newResult))
  .then((finalResult) => {
    console.log(`Got the final result: ${finalResult}`);
  })
  .catch(failureCallback);
```

**重要:** コールバック関数から処理結果を返すのを忘れないでください。さもないと後続のコールバック関数からその処理結果を利用することができなくなります（アロー関数を使った `() => x` は `() => { return x; }` の短縮形です）。前回ハンドラーがプロミスを始めたが、それを返さなかった場合、その決定を追跡する方法はもうなく、プロミスは「浮動」していると言います。

```js
doSomething()
  .then((url) => {
    // これを返すのを忘れていた
    fetch(url);
  })
  .then((result) => {
    // 結果は未定義です。前回ハンドラーからは何も
    // 返されないからです。
    // fetch() 呼び出しの返値を知る方法はもうありませんし、
    // 成功したかどうかもすべてわかりません。
  });
```

もし最後のハンドラーのプロミスが返されなければ、次の `then` ハンドラーが早く呼び出され、そのハンドラーが読み取る値が不完全になる可能性があります。

```js
const listOfIngredients = [];

doSomething()
  .then((url) => {
    // これを返すのを忘れていた
    fetch(url)
      .then((res) => res.json())
      .then((data) => {
        listOfIngredients.push(data);
      });
  })
  .then(() => {
    console.log(listOfIngredients);
    // Always [], because the fetch request hasn't completed yet.
  });
```

したがって、経験則として、処理がプロミスに遭遇したときはいつでもそれを返し、その処理を次の `then` ハンドラーに委ねるようにしてください。

```js
const listOfIngredients = [];

doSomething()
  .then((url) =>
    fetch(url)
      .then((res) => res.json())
      .then((data) => {
        listOfIngredients.push(data);
      }),
  )
  .then(() => {
    console.log(listOfIngredients);
  });

// または

doSomething()
  .then((url) => fetch(url))
  .then((res) => res.json())
  .then((data) => {
    listOfIngredients.push(data);
  })
  .then(() => {
    console.log(listOfIngredients);
  });
```

### 入れ子

上の2つの例では、最初のプロミス連鎖は別の `then()` ハンドラーの返値に入れ子になっていますが、 2 つ目は完全にフラットな連鎖を使用しています。単純なプロミス連鎖は、入れ子をせずにフラットに保つのがベストです。入れ子にすると、不注意な合成の結果になってしまう可能性があるからです。よくある間違いを参照してください。

入れ子は、`catch` 文の範囲を制限するための制御構造です。具体的には、入れ子になった `catch` は、そのスコープ以下のエラーのみを捕捉し、入れ子になったスコープの外側にある連鎖の上位のエラーは捕捉しません。正しく使用すれば、エラー回復の精度が高まります。

```js
doSomethingCritical()
  .then((result) =>
    doSomethingOptional(result)
      .then((optionalResult) => doSomethingExtraNice(optionalResult))
      .catch((e) => {}),
  ) // オプションの処理が失敗すれば無視して進める
  .then(() => moreCriticalStuff())
  .catch((e) => console.error(`Critical failure: ${e.message}`));
```

インデントではなく外側の `(` および `)` によってオプションの処理が入れ子になっていることに注意してください。

内側の `catch` 文は `doSomethingOptional()` と `doSomethingExtraNice()` からの失敗だけを捕捉し、捕捉したあと `moreCriticalStuff()` へと処理が続きます。重要なのは、もし `doSomethingCritical()` が失敗したらそのエラーは最後 (外側) の `catch` によってだけ捕捉されるということです。

### catch の後の連鎖

失敗、つまり `catch` の後に連鎖することも可能で、これは連鎖内の動作が失敗した後でも新しい動作を行うのに便利です。次の例を読んでください。

```js
new Promise((resolve, reject) => {
  console.log("Initial");

  resolve();
})
  .then(() => {
    throw new Error("Something failed");

    console.log("Do this");
  })
  .catch(() => {
    console.error("Do that");
  })
  .then(() => {
    console.log("Do this, no matter what happened before");
  });
```

これは下記のテキストを出力します。
```

Initial
Do that
Do this, no matter what happened before
```

**メモ:** "Do this" のテキストは "Something failed" エラーが拒否をを引き起こしたため出力されないことに注意してください。

よくある間違い
-------

プロミス連鎖を合成するときは以下のようなよくある間違いに気をつける必要があります。以下の例にいくつかの間違いが含まれています。

```js
// 悪い例。間違いを 3 つ見つけてください。

doSomething()
  .then(function (result) {
    // 内側の連鎖でプロミスを返していない + 不必要な入れ子
    doSomethingElse(result).then((newResult) => doThirdThing(newResult));
  })
  .then(() => doFourthThing());
// 連鎖の最後で catch を忘れている
```

最初の間違いは適切に連鎖を構成できていないことです。これは、新しいプロミスを作成したものの、それを返すのを忘れているときに起きます。結果として連鎖は壊れ、2 つの連鎖が独立して実行されることになります。これはつまり `doFourthThing()` は `doSomethingElse()` や `doThirdThing()` の終了を待たないことになり、おそらく意図せず並行して実行されることになります。別々の連鎖では別々のエラーハンドリングが行われるため、捕捉されないエラーが発生することになります。

2 つ目の間違いは不必要に入れ子にしていることです。入れ子にするということは内側のエラーハンドラーがのスコープが制限されるということであり、もしこれが意図していないものであれば、エラーが捕捉されない場合があります。これの変化形でプロミスのコンストラクターアンチパターンというものがあり、ネストに加えて、プロミスを既に使用しているコードを不必要なプロミスのコンストラクターでラップするというものです。

3 つ目の間違いは連鎖を `catch` で終わらせていないことです。プロミス連鎖が終わっていないと、多くのブラウザーでは、プロミスの拒否が捕捉されないことになります。下記のエラー処理を参照してください。

常識的には、常にプロミス連鎖を返すか終了させるかのどちらかで、新しいプロミスを受け取ったらすぐに返すようにして、物事をフラットにするのが良いでしょう。

```js
doSomething()
  .then(function (result) {
    // 完全な関数式を使用する場合は、プロミスを返します
    return doSomethingElse(result);
  })
  // アロー関数を使用する場合は、中括弧を省略し、暗黙のうちに結果を返す
  .then((newResult) => doThirdThing(newResult))
  // 前の連鎖したプロミスが結果を返しても、次のプロミスは必ずしも
  // それを使う必要はない。結果を消費しないハンドラーを渡すことが
  // できる
  .then((/\* 結果は無視されます \*/) => doFourthThing())
  // プロミスの連鎖は必ず catch ハンドラーで終わらせ、拒否が処理
  // されなくなることを避けるようにしましょう
  .catch((error) => console.error(error));
```

`() => x` は `() => { return x; }` の短縮形であることに注意してください。

これで適切なエラー処理が行われる 1 本の連鎖ができました。

`async`/`await` を使えば、すべてではないにしてもほとんどの問題は解決します。それと引き換えに、この構文で最もよくある間違いが `await` キーワードを忘れることです。

エラーの伝播
------

以前のコールバック地獄形式の記述方法では `failureCallback` を 3 回書く必要がありましたが、プロミス連鎖では 1 回で済みます。

```js
doSomething()
  .then((result) => doSomethingElse(result))
  .then((newResult) => doThirdThing(newResult))
  .then((finalResult) => console.log(`Got the final result: ${finalResult}`))
  .catch(failureCallback);
```

例外が発生すると、ブラウザーは連鎖をたどって `.catch()` ハンドラーか `onRejected` を探します。この動作は同期的なコードの動作ととてもよく似ています。

```js
try {
  const result = syncDoSomething();
  const newResult = syncDoSomethingElse(result);
  const finalResult = syncDoThirdThing(newResult);
  console.log(`Got the final result: ${finalResult}`);
} catch (error) {
  failureCallback(error);
}
```

ECMAScript 2017 の糖衣構文 `async`/`await` を使えば、非同期コードとそっくりになります。

```js
async function foo() {
  try {
    const result = await doSomething();
    const newResult = await doSomethingElse(result);
    const finalResult = await doThirdThing(newResult);
    console.log(`Got the final result: ${finalResult}`);
  } catch (error) {
    failureCallback(error);
  }
}
```

例えば、 `doSomething()` は以前と同じ関数なので、プロミスから `async`/`await` への変更に必要なリファクタリングは最小限です。`async`/`await` の構文については、非同期関数と `await` を参照してください。

プロミスは、発生する例外やプログラミングエラーも含めて、すべてのエラーを捕捉することで、コールバックピラミッドの根本的な欠陥を解決します。これは非同期処理を機能的に構成するために不可欠です。

プロミスの拒否イベント
-----------

プロミス拒否イベントがどのハンドラーによっても処理されなかった場合、そのイベントは呼び出しスタックの先頭にバブルし、ホスティングはそれを表面化する必要があります。ウェブでは、プロミスが拒否されるたびに、 2 種類のイベントのどちらかがグローバルスコープに送られます（一般的には、`window`か、ウェブワーカーで使用する場合は、`Worker`、または他のワーカーベースのインターフェイスです）。この 2 つのイベントは次の通りです。

`unhandledrejection`

プロミスが拒否されたものの、拒否ハンドラーが利用できない場合に送られます。

`rejectionhandled`

プロミスが拒否されたとき、実行者の `reject` 関数によって拒否が処理された後に送られます。

いずれの場合でも、この（`PromiseRejectionEvent` 型の）イベントは、拒否されたプロミスを示す `promise` プロパティと、そのプロミスが失敗した理由を表す `reason` プロパティを持ちます。

これらのイベントを使えば、プロミスのエラー処理のフォールバックを指定することができ、またプロミスを管理する際の問題をデバッグするのにも役立ちます。これらのハンドラーはコンテキストごとにグローバルであり、発生元に関わらず、すべてのエラーが同じイベントハンドラーによって処理されます。

Node.js では、プロミスの拒否の扱いは多少異なります。次のようにして Node.js に `unhandledRejection` イベント（名前の大文字小文字の違いに注意）のハンドラーを追加することで、未処理の拒否を捕捉することができます。

```js
process.on("unhandledRejection", (reason, promise) => {
  // "promise" および "reason" の値を検査するコードをここに追加
});
```

Node.js では、エラーがコンソールに記録されること (そうしないと発生する既定のアクション) を防ぐには、 `process.on()` リスナーを追加するだけで十分です。ブラウザーの実行環境の `preventDefault()` のようなことを行う必要はありません。

しかし、 `process.on` リスナーを追加しても、その中に拒否されたプロミスを処理するコードがなければ、プロミスは床に落ちて暗黙に無視されてしまいます。そのため、できればリスナー内にコードを追加して、拒否されたプロミスをそれぞれ検証し、実際のコードのバグが原因ではないことを確認してください。

合成
--

非同期処理を同時に実行するための 4 つの合成ツールがあります。 `Promise.all()`、`Promise.allSettled()`、`Promise.any()`、`Promise.race()` です。

以下のように複数の処理を並行に開始し、すべてが終了するのを待つことができます。

```js
Promise.all([func1(), func2(), func3()]).then(([result1, result2, result3]) => {
  // result1, result2, result3 を使用
});
```

注意すべきは、配列の中の 1 つのプロミスが拒否されると、 `Promise.all()` がそのエラーを発生させ、他の処理を中断することです。これにより、予期せぬ状態や振る舞いが発生する可能性があります。 `Promise.allSettled()` は、解決する前にすべての操作が完了することを保証する別の合成ツールです。

これらのメソッドはすべてプロミスを並列処理します。一連のプロミスは同時に開始され、他にも待つことはありません。いくつかの賢い JavaScript を使用することで、逐次合成が可能です。

```js
[func1, func2, func3]
  .reduce((p, f) => p.then(f), Promise.resolve())
  .then((result3) => {
    // result3 を使用
  });
```

この例では、非同期関数の配列をプロミス連鎖に縮小しています。上のコードは次のコードと同じです。

```js
Promise.resolve()
  .then(func1)
  .then(func2)
  .then(func3)
  .then((result3) => {
    // result3 を使用
  });
```

これは、関数型プログラミングでよく見られる、再利用可能な合成関数にすることができます。

```js
const applyAsync = (acc, val) => acc.then(val);
const composeAsync =
  (...funcs) =>
  (x) =>
    funcs.reduce(applyAsync, Promise.resolve(x));
```

`composeAsync()` 関数は、任意の数の関数を引数として受け取り、合成パイプラインに渡される初期値を受け取る新しい関数を返します。

```js
const transformData = composeAsync(func1, func2, func3);
const result3 = transformData(data);
```

直列的な合成は async/await でもっと単純に書くことができます。

```js
let result;
for (const f of [func1, func2, func3]) {
  result = await f(result);
}
/\* 最終的な結果 (すなわち result3) を使用 \*/
```

しかし、プロミスを逐次的に構成する前に、それが実に必要かどうかを検討してください。あるプロミスの実行が他のプロミスの結果に依存していない限り、それらが不必要にブロックし合わないように、常にプロミス並列処理を実行する方がよいのです。

古いコールバック API をラップする Promise の作成
-------------------------------

`Promise` はコンストラクターを使って 1 から生成すこともできます。これが必要になるのは古い API をラップする場合のみでしょう。

理想的には、すべての非同期関数はプロミスを返すはずですが、残念ながら API の中にはいまだに古いやり方で成功/失敗用のコールバックを渡しているものがあります。顕著な例としては `setTimeout()` 関数があります。

```js
setTimeout(() => saySomething("10 seconds passed"), 10 \* 1000);
```

古い様式であるコールバックとプロミスの混在は問題を引き起こします。というのは、`saySomething()` が失敗したりプログラミングエラーを含んでいた場合に、そのエラーをとらえられないからです。`setTimeout` にその責任があります。

幸いにも `setTimeout` をプロミスの中にラップすることができます。良いやり方は、問題のある関数をできる限り低い水準でラップした上で、直接呼び出さないようにすることです。

```js
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

wait(10 \* 1000)
  .then(() => saySomething("10 seconds"))
  .catch(failureCallback);
```

プロミスのコンストラクターは、プロミスを手動で解決したり拒否したりするための実行関数を受け取ります。 `setTimeout()` は実に失敗しないので、今回は拒否を省きました。これがどのように動作するのかについては、 `Promise()` を参照してください。

タイミング
-----

最後に、登録されたコールバックがいつ呼び出されるかについて、より技術的な詳細を見ていきます。

### 保証

コールバックベースの API では、いつ、どのようにコールバックが呼び出されるかは、 API の実装者に依存します。例えば、コールバックは同期的に呼び出されることもあれば、非同期的に呼び出されることもあります。

```js
function doSomething(callback) {
  if (Math.random() > 0.5) {
    callback();
  } else {
    setTimeout(() => callback(), 1000);
  }
}
```

上記の設計は、いわゆる「ザルゴの状態」という状態になるため、強く避けるべきです。非同期 API の設計の文脈では、これはコールバックがある場合には同期的に呼び出されますが、他の場合には非同期的に呼び出され、呼び出し側に曖昧さを作成することを意味しています。さらに詳しい背景については、この用語が最初に正式に表示された記事 Designing APIs for Asynchrony を参照してください。この API 設計により、副作用を分析することが難しくなります。

```js
let value = 1;
doSomething(() => {
  value = 2;
});
console.log(value); // 1 or 2?
```

一方で、プロミスは制御の反転という形です。コールバックが呼び出されるタイミングを API 実装者が制御することはありません。その代わりに、コールバックキューを維持し、いつコールバックを呼び出すかを決定する仕事はプロミスの実装に委ねられ、 API ユーザーと API 開発者の両方は、自動的に以下のような強力な意味づけ保証を得ることができます。

* `then()` で追加されたコールバックは、 JavaScript のイベントループの現在の実行の完了より前に呼び出されることはありません。
* これらのコールバックは、プロミスが表す非同期処理の成功や失敗の後に追加されても呼び出されます。
* `then()` を複数回呼び出すことで、複数のコールバックを追加することができます。これらは挿入された順に次々と呼び出されます。

想定外の事態とならないよう、たとえすでに解決されたプロミスであっても、 `then()` に渡された関数が同期的に呼び出されることはありません。

```js
Promise.resolve().then(() => console.log(2));
console.log(1);
// Logs: 1, 2
```

渡された関数はすぐに実行されるのではなく、マイクロタスクのキューに入れられます。後で（生成した関数が終了し、 JavaScript の実行スタックが空になってから）、イベントループに制御が戻される直前、つまりかなり早い段階で実行されます。

```js
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

wait(0).then(() => console.log(4));
Promise.resolve()
  .then(() => console.log(2))
  .then(() => console.log(3));
console.log(1); // 1, 2, 3, 4
```

### タスクキューとマイクロタスク

プロミスのコールバックはマイクロタスクとして処理され、 `setTimeout()` コールバックはタスクキューとして扱われます。

```js
const promise = new Promise((resolve, reject) => {
  console.log("Promise callback");
  resolve();
}).then((result) => {
  console.log("Promise callback (.then)");
});

setTimeout(() => {
  console.log("event-loop cycle: Promise (fulfilled)", promise);
}, 0);

console.log("Promise (pending)", promise);
```

上記のコードの出力は次の通りです。
```

Promise callback
Promise (pending) Promise {<pending>}
Promise callback (.then)
event-loop cycle: Promise (fulfilled) Promise {<fulfilled>}
```

詳しくは、タスクとマイクロタスク (en-US)を参照してください。

### プロミスとタスクが衝突するとき

プロミスとタスク（イベントやコールバックなど）が予測不可能な順序で発行されている状況に遭遇した場合、マイクロタスクを使用して状態をチェックしたり、プロミスが条件付きで作成されている場合にプロミスのバランスを取ったりすることが有益である可能性があります。

マイクロタスクがこの問題の解決に役立つと思われる場合は、マイクロタスクガイドで `queueMicrotask()` を使用して関数をマイクロタスクとしてキューに入れる方法について詳しく説明しています。

関連情報
----

* `Promise`
* `async function`
* `await`
* Promises/A+ specification
* We have a problem with promises on pouchdb.com (2015)
* « 前のページ
* 次のページ »


イテレーターとジェネレーター - JavaScript

イテレーターとジェネレーター
==============

* « 前のページ
* 次のページ »

コレクション内の各アイテムに対する処理は非常に一般的な操作です。JavaScript では簡単な `for` ループから `map()`、`filter()` にいたるまで、コレクションに対する反復処理の複数の方法を提供します。

イテレーターとジェネレーターは、コア言語の内部に反復処理が直接的に取り入れられており、`for...of` ループの動作を簡単にカスタマイズできる仕組みをもたらします。

詳細についてはこちらもご覧ください:

* Iteration protocols
* `for...of`
* `function*` と ジェネレーター
* `yield` と `yield*`
イテレーター
------

JavaScript では、**イテレーター**はシーケンスおよび潜在的には終了時の戻り値を定義するオブジェクトです。

より具体的に言うと、イテレーターは、次の 2 つのプロパティを持つオブジェクトを返す `next()` メソッドを持つことによってイテレータープロトコルを実装するオブジェクトです。

`value`

反復シーケンスの次の値

`done`

シーケンスの最後の値が既に消費されている場合に `true` となります。`done` と並んで `value` が存在する場合、それがイテレーターの戻り値となります。

イテレーターオブジェクトが作成されると、`next()` を繰り返し呼び出すことによって、明示的に反復することができます。イテレーターを反復することを、イテレーターを消費すると言います。一般的に 1 回しか実行できないためです。終了値が返された後、さらに `next()` を呼び出しても、単に `{done: true}` を返し続けます。

Javascript で最も一般的なイテレーターは配列イテレーターで、配列の各値を順番に返します。

すべてのイテレーターを配列として表現できるとは想像するのは容易ですが、これは真実ではありません。配列は完全に割り当てなければなりませんが、イテレーターは必要なだけで消費されるため、0 から Infinity までの整数の範囲など、無限のサイズのシーケンスを表現できます。

ここでは、それを行うことができる例を示します。`start` (包括) から `end` (排他) までの一連の整数を定義する単純な範囲のイテレーターの作成を可能にします。最終的な戻り値は、作成したシーケンスのサイズあり、変数 `iterationCount` で追跡されます。

```js
function makeRangeIterator(start = 0, end = Infinity, step = 1) {
  let nextIndex = start;
  let iterationCount = 0;

  const rangeIterator = {
    next: function () {
      let result;
      if (nextIndex < end) {
        result = { value: nextIndex, done: false };
        nextIndex += step;
        iterationCount++;
        return result;
      }
      return { value: iterationCount, done: true };
    },
  };
  return rangeIterator;
}
```

このイテレーターを使えば、次のようになります:

```js
const it = makeRangeIterator(1, 10, 2);

let result = it.next();
while (!result.done) {
  console.log(result.value); // 1 3 5 7 9
  result = it.next();
}

console.log("Iterated over sequence of size: ", result.value); // [5 numbers returned, that took interval in between: 0 to 10]
```

**メモ:** 特定のオブジェクトがイテレーターであるかどうかは考えても知ることはできません。それが必要な場合は、反復可能オブジェクトを使用してください。

ジェネレーター関数
---------

カスタムイテレーターは便利なツールですが、その作成には内部状態を明示的に維持する必要があるため、慎重なプログラミングが必要です。ジェネレーター関数は強力な代替手段を提供します。実行が連続していない単一の関数を記述することによって反復アルゴリズムを定義できます。ジェネレーター関数は、`function*` 構文を使用して記述されます。

最初に呼び出されると、ジェネレーター関数はコードを実行せず、ジェネレーターと呼ばれるある種のイテレーターを返します。ジェネレーターの **next** メソッドを呼び出すことによって値が消費されると、ジェネレーター関数は **yield** キーワードを検出するまで実行します。

この関数は、必要な回数だけ呼び出すことができ、毎回新しいジェネレーターを返しますが、各ジェネレーターは 1 回のみ反復することができます。

上の例に適用してみましょう。このコードの動作は同じですが、実装は書くのも読むのもはるかに容易になります。

```js
function\* makeRangeIterator(start = 0, end = 100, step = 1) {
  let iterationCount = 0;
  for (let i = start; i < end; i += step) {
    iterationCount++;
    yield i;
  }
  return iterationCount;
}
```

反復可能オブジェクト
----------

オブジェクトは、`for...of` 構文でループされる値など反復動作を定義する場合、**反復可能オブジェクト**です。`Array` や `Map` のような組み込み型の中にはデフォルトの反復動作を持つものがありますが、他の型 (`Object` など) は持っていません。

**反復可能オブジェクト**にするには、オブジェクトは **@@iterator** メソッドを実装する必要があります。つまり、オブジェクト (またはプロトタイプチェーン上のオブジェクトのうちの 1 つ) に `Symbol.iterator` キーを持つプロパティが必要です 。

反復可能オブジェクトは 1 回だけでも 2 回以上でも反復することができます。どちらが当てはまるかは、プログラマに任されています。

一度しか反復することができない反復可能オブジェクト (例えば、ジェネレーター) は、通常 **@@iterator** メソッドから **this** を返します。何度も繰り返し可能なものは、**@@iterator** の各呼び出しで新しいイテレーターを返す必要があります。

```js
function\* makeIterator() {
  yield 1;
  yield 2;
}

const it = makeIterator();

for (const itItem of it) {
  console.log(itItem);
}

console.log(it[Symbol.iterator]() === it); // true;

// This example show us generator(iterator) is iterable object,
// which has the @@iterator method return the it (itself),
// and consequently, the it object can iterate only \_once\_.

// If we change it's @@iterator method to a function/generator
// which returns a new iterator/generator object, (it)
// can iterate many times

it[Symbol.iterator] = function\* () {
  yield 2;
  yield 1;
};
```

### ユーザー定義の反復可能オブジェクト

以下のようにして反復可能オブジェクトを自作することができます:

```js
var myIterable = {
    \*[Symbol.iterator]() {
        yield 1;
        yield 2;
        yield 3;
    }
}

for (let value of myIterable) {
    console.log(value);
}
// 1
// 2
// 3

or

[...myIterable]; // [1, 2, 3]
```

### 組み込み反復可能オブジェクト

`String`、`Array`、`TypedArray`、`Map`、`Set` はすべて組み込み反復可能オブジェクトです。これらのオブジェクトはすべて、そのプロトタイプオブジェクトに `Symbol.iterator` メソッドを備えているためです。

### 反復可能オブジェクトが必要な構文

`for-of` ループ、`yield*` などの文や式は、反復可能オブジェクトを必要とします。

```js
for (let value of ["a", "b", "c"]) {
  console.log(value);
}
// "a"
// "b"
// "c"

[..."abc"];
// ["a", "b", "c"]

function\* gen() {
  yield\* ["a", "b", "c"];
}

gen().next();
// { value: "a", done: false }

[a, b, c] = new Set(["a", "b", "c"]);
a;
// "a"
```

高度なジェネレーター
----------

ジェネレーターは要求に応じて yield 文により生成される値を計算しており、多くの計算が必要な一連のデータを効率的に表現したり、前出のとおり無限のシーケンスを表現したりすることを可能にします。

ジェネレーターの内部状態を変更するのための値を `next()` メソッドで受け入れることもできます。`next()` に渡された値は `yield` が受け取ります。最初 `next()` の呼び出しに値を渡しても常に無視されることに注意してください。

**メモ:** `next()` の*最初の*呼び出しに渡された値は常に無視されます。

以下のフィボナッチ数列ジェネレーターでは数列を再起動するのに `next(x)` を使っています:

```js
function\* fibonacci() {
  let current = 0;
  let next = 1;
  while (true) {
    let reset = yield current;
    [current, next] = [next, next + current];
    if (reset) {
      current = 0;
      next = 1;
    }
  }
}

const sequence = fibonacci();
console.log(sequence.next().value); // 0
console.log(sequence.next().value); // 1
console.log(sequence.next().value); // 1
console.log(sequence.next().value); // 2
console.log(sequence.next().value); // 3
console.log(sequence.next().value); // 5
console.log(sequence.next().value); // 8
console.log(sequence.next(true).value); // 0
console.log(sequence.next().value); // 1
console.log(sequence.next().value); // 1
console.log(sequence.next().value); // 2
```

ジェネレーターの `throw()` メソッドを呼び出して発生すべき例外値を渡すことで、ジェネレーターに例外を強制的に発生させることができます。これにより、まるで停止中の `yield` が `throw value` 文に替わったかのように、ジェネレーターが停止した際の状況に応じて例外が発生します。

例外がジェネレーター内部で捕捉されない場合は、`throw()` を通してその例外が呼び出し元へと伝播し、その後 `next()` を呼び出した結果の `done` プロパティは `true` となります。

またジェネレーターは、与えられた値を返してジェネレーター自身の処理を終了させる `return(value)` メソッドを持っています。

* « 前のページ
* 次のページ »


入門編 - JavaScript

入門編
===

* « 前のページ
* 次のページ »

本章では JavaScript について紹介し、その基本的な概念について説明します。

事前に知っておくべきこと
------------

このガイドは、以下の基礎的な予備知識を持っていることを前提としています。

* インターネットと World Wide Web (WWW) についての一般的な理解。
* HyperText Markup Language (HTML) についての実用的な知識。
* プログラミングの経験。プログラミングが初めての方は、 JavaScript についてのメインページにあるチュートリアルをお試しください。
JavaScript の情報はどこにあるか
---------------------

MDN には以下の JavaScript 関連ドキュメントがあります。

* ウェブ開発を学ぶでは、初心者に向けた情報を提供し、プログラミングとインターネットの基本的なコンセプトを提供しています。
* JavaScript ガイド（このガイド）では、JavaScript 言語とその対象に関する概要を提供しています。
* JavaScript リファレンスは、JavaScript の詳細なリファレンス素材を提供しています。

JavaScript を初めて学ぶ方は、学習領域、および JavaScript ガイドの記事から始めてください。基礎をしっかり学んだら、JavaScript リファレンスを利用して、個々のオブジェクトや文についての詳細を得てください。

JavaScript とは何か
---------------

JavaScript は、クロスプラットフォームで動作するオブジェクト指向のスクリプト言語で、ウェブページをインタラクティブにするために使用されます（例えば、複雑なアニメーション、押下可能なボタン、ポップアップメニューなどを設けることです）。 Node.js のような、より高度なサーバー側のバージョンの JavaScript もあり、ファイルをダウンロードするだけでなく（複数のコンピューター間でのリアルタイムの連携など）、ウェブサイトに多くの機能を追加することができます。ホスト環境（例えばウェブブラウザー）内では、 JavaScript とその環境のオブジェクトが結びつけられ、プログラム制御が可能になっています。

JavaScript には、`Array`、`Date`、 `Math` といったオブジェクトからなる基本的なライブラリー、そして演算子、制御構造、文といったプログラミング言語の要素からなる主要な機能が含まれています。 JavaScript のコア機能は、追加のオブジェクトを補うことで、様々な目的に拡張することができます。例えば以下のようなものです。

* *クライアントサイド JavaScript* は、ブラウザーとその*ドキュメントオブジェクトモデル* (DOM) を制御するオブジェクトを提供することにより、コア言語を拡張します。例えば、クライアントサイドでの拡張により、アプリケーションが HTML フォーム上に要素を配置したり、マウスクリック、フォーム入力、ページ移動といったユーザーのイベントに応答したりできます。
* *サーバーサイド JavaScript* は、 JavaScript を使ったサーバーの稼働に関連するオブジェクトを提供することにより、コア言語を拡張します。例えば、サーバーサイドでの拡張により、アプリケーションがデータベースとやり取りしたり、アプリケーション内のある呼び出しから別の呼び出しまでの間を情報が連続性を保ったり、サーバー上のファイルを操作したりできます。

これはつまり、ブラウザー内で JavaScript がウェブページ (DOM) の見た目を変更できるということです。同様に、サーバー上の Node.js の JavaScript は、ブラウザー内に記述されたコードからの独自のリクエストに応答できます。

JavaScript と Java
-----------------

JavaScript と Java はいくつかの点では似ていますが、その他の点では全くの別物です。 JavaScript 言語は Java と共通点がありますが、Java のような静的型付けと強い型検査を持っていません。 LiveScript から JavaScript へ改名する理由ともなった、Java が持つ多くの式構文、命名規則と基本的な制御フローを JavaScript は踏襲しています。

宣言によって作られたクラスから構成される Java のコンパイル時システムとは対照的に、JavaScript は、数値や論理値、文字列を表す少数のデータ型をベースにしたランタイムシステムに対応しています。 JavaScript は、より一般的であるクラスベースのオブジェクトモデルの代わりに、プロトタイプベースのオブジェクトモデルを持っています。プロトタイプベースモデルは動的な継承を実現します。つまり、様々なオブジェクトから継承できるということです。また JavaScript は、特殊な宣言型を必要としない関数に対応しています。関数はオブジェクトのプロパティに設定することができ、弱い型付けのメソッドとして実行することができます。

JavaScript は Java に比べてとても自由な形式を持つ言語です。変数、クラス、メソッドをあまねく宣言する必要はありません。メソッドが public か private か、あるいは protected かどうかを気に掛けることも、インターフェイスを実装する必要もありません。変数、引数、そして型を返す関数は厳密に型付けされていません。

Java は高速実行と型安全のために設計されたクラスベースのプログラミング言語です。型安全というのは、例えば、 Java の整数値をオブジェクトの参照に型変換したり、有害な Java のバイトコードがプライベートなメモリーにアクセスしたりすることができないということです。 Java のクラス継承と強い型付けは、一般的に密結合されたオブジェクト階層を必要とします。こうした前提条件によって Java のプログラミングは JavaScript のプログラミングに比べて複雑なものとなります。

それに対して、 JavaScript は HyperTalk や dBASE といった一連の小規模で動的型付けを持つ言語の精神を受け継いでいます。これらのスクリプト言語は、より簡素な構文、専門化された組み込み関数、最小限の要件でオブジェクトを生成できることなどで、より多くの人々にプログラミングツールを提供しています。

| JavaScript | Java |
| --- | --- |
| オブジェクト指向。オブジェクトのデータ型に区別はない。継承はプロトタイプベースの機構を通して行われ、プロパティとメソッドはどんなオブジェクトにも動的に追加できる。 | クラスベース。オブジェクトはクラスとそのクラス階層によって継承されたインスタンスとに分かれている。クラスとインスタンスは動的にプロパティやメソッドを追加することができない。 |
| 変数のデータ型は宣言が不要 (動的型付け、弱い型付け)。 | 変数のデータ型は宣言が必須 (静的型付け、強い型付け)。 |
| ハードディスクには自動的に書き込みできない。 | ハードディスクには自動的に書き込みできる。 |

JavaScript と ECMAScript 仕様書
---------------------------

JavaScript は、ヨーロッパの情報通信システム標準化団体である Ecma International （ECMA は、以前は European Computer Manufacturers Association の頭字語）で標準化されており、 JavaScript をベースとした国際的なプログラミング言語の標準化を実現しています。この標準化された JavaScript は ECMAScript と呼ばれ、この規格に対応するすべてのアプリケーションで同じように動作します。企業は、このオープンスタンダードな言語を使って、 JavaScript の実装を開発することができます。 ECMAScript 標準は、 ECMA-262 仕様書に記載されています。

ECMA-262 標準は、ISO（International Organization for Standardization、国際標準化機構）により ISO-16262 としても承認されています。また仕様書は、Ecma International のウェブサイトでも確認できます。ECMAScript 仕様書には、World Wide Web Consortium (W3C) によって標準化されているドキュメントオブジェクトモデル (DOM) は記載されていません。 DOM はスクリプトから利用できる HTML 文書のオブジェクトを定義しています。 JavaScript でプログラミングする際に使われる様々な技術のさらに詳しい情報は、JavaScript 技術概説の記事を参考にしてください。

### JavaScript ドキュメント vs ECMAScript 仕様書

ECMAScript 仕様書は ECMAScript を実装するために必要な一連の要件です。 ECMAScript の実装やエンジン（Firefox の SpiderMonkey や Chrome の V8 など）で、標準に準拠した言語機能を使用したい場合に有益なものです。

ECMAScript のドキュメントは、スクリプトのプログラマーを支援するためのものでは*ありません*。スクリプトを記述する際には JavaScript のドキュメントを使いましょう。

ECMAScript 仕様書は、JavaScript プログラマーにあまり馴染みのない専門用語と文法で書かれています。この言語を解説したものと ECMAScript とは異なるところがあるかもしれませんが、この言語自体は同じものです。JavaScript は、ECMAScript 仕様書で描かれた機能すべてに対応しています。

JavaScript のドキュメントは、JavaScript プログラマーに適した形で言語の特徴について記述しています。

JavaScript を始めよう
----------------

JavaScript を始めるのは簡単です。必要なものは、最新のウェブブラウザーだけです。このガイドでは最新の Firefox でのみ利用できる JavaScript の機能をいくつか使用するので、最新の Firefox を使用することをお勧めします。

Firefox に組み込まれている*ウェブコンソール*ツールは、JavaScript を試すのに役立ちます。シングルライン入力モードとマルチライン入力モードの 2 つのモードで使用できます。

### ウェブコンソールでの単一行入力

ウェブコンソールには、現在読み込まれているウェブページの情報が表示されるほか、現在のページで JavaScript 式を実行するために使用できる JavaScript インタープリターも含まれています。

ウェブコンソールを開くには（Windows と Linux では `Ctrl`+`Shift`+`I`、Mac では `Cmd`-`Option`-`K`）、Firefox の**ツール**メニューを開き、**ウェブ開発 ▶ ウェブコンソール**を選択します。

ブラウザーウィンドウの下部にウェブコンソールが表示されます。コンソールの下部に沿って、 JavaScript を入力するための入力行があり、出力は上のパネルに表示されます。

![下部にウェブコンソールを開くためのブラウザーウインドウで、 2 行の入出力を含む。その下記にはテキストを入力することができます。](/ja/docs/Web/JavaScript/Guide/Introduction/2019-04-04_00-15-29.png)

コンソールは `eval` と全く同じように動作します。最後に入力された式が返されます。分かりやすくするために、コンソールに何か入力されるたびに、実際には `eval` の周りを `console.log` で囲むと想像してみると、このようになります。

```js
console.log(eval("3 + 5"));
```

### ウェブコンソールでの複数行入力

ウェブコンソールの単一行入力モードは、JavaScript の式をすばやくテストするのには最適ですが、複数行を実行するには向いていません。より複雑な JavaScript の場合は、複数行の入力モードが使用できます。

### Hello world

JavaScript を書き始めるあたり、ウェブコンソールを複数行モードで開いて、初めての JavaScript コード "Hello world" を書いてみましょう。

```js
(function () {
  "use strict";
  /\* コードの開始 \*/
  function greetMe(yourName) {
    alert(`Hello ${yourName}`);
  }

  greetMe("World");
  /\* コードの終了 \*/
})();
```

`Cmd`+`Enter` または `Ctrl`+`Enter` を押して（または**実行ボタン**をクリック）、結果を見てみましょう。

このガイドの以降のページでは、より複雑なアプリケーションを作成できるように、 JavaScript の構文と言語の特徴を紹介します。

ですが、しばらくの間、常にあなたのコードの先頭に `(function(){"use strict";` を、コードの最後に `})();` を記述することを忘れないでください。厳格モードと IIFE の記事でこれらが何であるかを説明していますが、今のところは次のように捉えておいてください。

1. 初心者をつまずかせる、JavaScript のセマンティクスを避ける。
2. コンソールで実行されたコードスニペットが相互に影響することを防止する（たとえば、あるコンソールの実行で作成されたものを別のコンソールの実行に使用するなど）。
* « 前のページ
* 次のページ »


文法とデータ型 - JavaScript

文法とデータ型
=======

* « 前のページ
* 次のページ »

この節では JavaScript の基本文法、変数宣言、データ型、リテラルについて説明します。

基本
--

JavaScript は Java, C, C++ から構文の多くを取り入れていますが、Awk, Perl, Python からも影響を受けています。

また、JavaScript は**大文字と小文字を区別**し、また **Unicode** 文字セットを使用しています。例えば、Früh という単語 (ドイツ語で "early" という意味) を変数名として使用することができます。

```js
const Früh = "foobar";
```

ただし、JavaScript は大文字と小文字を区別するので、`früh` という変数は `Früh` と同じではありません。

JavaScript では、命令は文 (statement) と呼ばれ、セミコロン (;) によって区切られています。

文が単独の行で書かれている場合、文の後にセミコロンは必要ではありません。しかし、行の中に複数の文が必要な場合は、セミコロンで区切る*必要*があります。

**メモ:** ECMAScript も文末に自動的にセミコロンを挿入するルールがあります (ASI)。（詳しくは、JavaScript の 字句文法についての詳細なリファレンスを参照してください。）

必須ではないとしても、文の後に常にセミコロンを記述することをお勧めします。これによって、コード中にバグが発生する機会を減らすことができます。

JavaScript のソーステキストは左から右にスキャンされ、*トークン*、*制御文字*、*改行文字*、*コメント*、ホワイトスペース等の入力要素の並びに変換されます。（空白、タブ、改行はホワイトスペースとみなされます。）

コメント
----

**コメント**の構文は C++ やその他の多くの言語と一緒です。

```js
// 一行のコメント

/\* もっと長い、
 複数行からなるコメント
 \*/
```

ブロックコメントを入れ子にすることはできません。これは、コメントに誤って `*/` シーケンスを記載してしまい、コメントが終了してしまう場合によく起こります。

```js
/\* ただし、/\* 入れ子のコメントは \*/ できず、SyntaxError となります \*/
```

この場合、`*/`のパターンを分割する必要があります。例えば、バックスラッシュを挿入したりします。

```js
/\* スラッシュをエスケープすることで /\* コメントを入れ子に \*\/ することができます \*/
```

コメントはホワイトスペースのように扱われ、スクリプトの実行から除外されます。

**メモ:** 一部の JavaScript ファイルの先頭で、`#!/usr/bin/env node` のような第三の種類のコメントを見かけることもあるかもしれません。

これは**ハッシュバンコメント**構文と呼ばれ、スクリプトの実行に使用したい特定の JavaScript エンジンへのパスを指定するのに使用される特殊なコメントです。詳しくはハッシュバンコメントを参照してください。

宣言
--

JavaScript には変数を宣言する方法が 3 種類あります。

`var`

変数を宣言し、ある値に初期化することもできる。

`let`

ブロックスコープのローカル変数を宣言し、ある値に初期化することもできる。

`const`

ブロックスコープで読み取り専用の名前付き定数を宣言する。

### 変数

変数はアプリケーションで値を表す記号的な名前として使用します。変数の名前は識別子とも呼ばれ、一定のルールに従わなくてはなりません。

JavaScript の識別子は必ず文字、アンダースコア (`_`)、あるいはドル記号 (`$`) から始まらなくてはなりません。続く文字には数字 (`0`–`9`) も使用できます。JavaScript は大文字と小文字を区別するため、使用できる文字には "`A`" から "`Z`" （大文字）に加えて "`a`" から "`z`" （小文字）も含まれます。

`å` や `ü` などの ISO 8859-1 や Unicode 文字（詳しくはこのブログ記事または字句文法のリファレンスを参照）も識別子に使用することができます。Unicode エスケープシーケンスも識別子に使用することができます。

`Number_hits`、`temp99`、`_name` などは、正しい名前の一例です。

### 変数の宣言

変数を宣言する方法は 2 通りあります。

* キーワード `var` を使う（例 `var x = 42`）。この構文は、*実行コンテキスト*によって、**ローカル変数**と**グローバル変数**の両方の宣言に使用できます。
* `const` または `let` キーワードを使う。例えば、`let y = 13`。この構文はブロックスコープのローカル変数を宣言することができます。（以下にある変数のスコープをご覧ください。）

分割代入構文を使用して、複数の変数を宣言することができます。例えば、`const { bar } = foo` とします。これは `bar` という名前の変数を作成し、オブジェクト `foo` の同名キーから対応する値を代入します。

変数は使用する前に常に宣言するようにしてください。 JavaScript は未宣言の変数に代入することができ、 **未宣言のグローバル** 変数を生成します。これは厳格モードではエラーとなるものであり、完全に避けるべきです。

### 宣言と初期化

`let x = 42` のような文では、`let x` の部分は *宣言* と呼ばれ、`= 42` の部分は *初期化子* と呼ばれます。宣言では、`ReferenceError` を発生させることなく、コードの後半で変数にアクセスできるようにし、初期化子では、変数に値を代入しています。`var` と `let` の宣言では、初期化子はオプションです。もし変数が初期化子なしで宣言された場合、その変数には `undefined` という値が代入されます。

```js
let x;
console.log(x); // "undefined" を出力
```

実質的に、`let x = 42` は `let x; x = 42` と同等です。

`const` 宣言は宣言後のあらゆる代入を禁止しているため、常に初期化子が必要です。暗黙のうちに `undefined` で初期化することは、おそらくプログラマーのミスです。

```js
const x; // SyntaxError: Missing initializer in const declaration
```

### 変数のスコープ

変数は以下のスコープのいずれかに所属します。

* グローバルスコープ: スクリプトモードで実行するすべてのコードの既定のスコープです。
* モジュールスコープ: モジュールモードで実行されるコードのスコープです。
* 関数スコープ: 関数で作成されるスコープです。

それに加えて、 `let` または `const` で宣言された変数は、もう一つのスコープに所属します。

* ブロックスコープ: 波括弧の組で生成されるスコープ（ブロック）。

変数を関数の外側で宣言すると、現在の文書のどのコードからも使用できるようになるため、*グローバル* （大域）変数と呼ばれます。変数を関数の内部で宣言すると、その関数の中でしか使用できないため、*ローカル* （局所）変数と呼ばれます。

`let` および `const` の宣言は、宣言されたブロック文のスコープになることもあります。

```js
if (Math.random() > 0.5) {
  const y = 5;
}
console.log(y); // ReferenceError: y is not defined
```

ただし、 `var` で生成された変数はブロックスコープにはならず、そのブロックが存在する *関数（またはグローバルスコープ）* に局所的になります。

例えば、以下のコードでは `5` が出力されます。これは、`x` のスコープがグローバルコンテキスト（またはこのコードが関数の中であれば関数コンテキスト）だからです。`x` のスコープは中間の `if` 文のブロックに限定されません。

```js
if (true) {
  var x = 5;
}
console.log(x); // x は 5
```

### 変数の巻き上げ

`var` で宣言された変数は巻き上げが行われ、その変数がまだ宣言されていない場合でも、そのスコープ内のどこでも参照することができるようになります。変数 `var` の宣言は、その関数やグローバルスコープの先頭に「持ち上げられる」ように見ることができます。しかし、宣言される前に変数にアクセスすると、その値は常に `undefined` となります。なぜなら、その変数の *宣言* だけが巻き上げられ、 *初期化* は巻き上げられないからです。

```js
console.log(x === undefined); // true
var x = 3;

(function () {
  console.log(x); // undefined
  var x = "local value";
})();
```

上記の例は以下と同様に解釈されます。

```js
var x;
console.log(x === undefined); // true
x = 3;

(function () {
  var x;
  console.log(x); // undefined
  x = "local value";
})();
```

巻き上げがあるため、関数内にあるすべての `var` 文は関数内で可能な限り先頭に近い位置に置くべきです。これはコードの明確さを高める最善の方法です。

`let` と `const` が巻き上げられるかどうかは、定義の議論の余地があります。変数宣言の前にブロック内で変数を参照すると常に `ReferenceError` が発生します。ブロックの始まりから宣言が処理されるまで、変数は「一時的なデッドゾーン」にあるからです。

```js
console.log(x); // ReferenceError
const x = 3;

console.log(y); // ReferenceError
let y = 3;
```

`var` 宣言は宣言だけを巻き上げ、その値は巻き上げませんが、関数宣言は完全に巻き上げられ、そのスコープ内のどこでも安全に関数を呼び出すことができます。より詳しい説明は、用語集の巻き上げの項目を参照してください。

### グローバル変数

グローバル変数は、実際には*グローバルオブジェクト*のプロパティです。

ウェブページでのグローバルオブジェクトは `window` になります。そのため `window.変数名` という構文を用いてグローバル変数の設定やアクセスができます。すべての環境において、グローバル変数にアクセスするために `globalThis` 変数（これ自体がグローバル変数です）を使用することができます。

したがって、あるウィンドウやフレームで宣言したグローバル変数は、そのウィンドウやフレームの名前を指定することで別の `window` や `frame` からアクセスできます。例えば `phoneNumber` 変数を文書内で宣言すると、`iframe` から `parent.phoneNumber` としてその変数を参照できます。

### 定数

`const` キーワードを用いて、読み取り専用の名前付き定数を作成できます。定数の識別子の構文は、変数の識別子の構文と同じです。識別子は文字、アンダースコア、ドル記号 (`$`) から始めなくてはならず、アルファベット、数値、アンダースコアを含めることができます。

```js
const PI = 3.14;
```

定数は代入によって値を変えたり、スクリプト実行中に再宣言したりすることはできません。定数はある値に初期化しなければなりません。定数のスコープルールは、`let` によるブロックスコープ変数と同じです。

以下の例のように、同一スコープ内で関数や変数と同じ名前の定数を宣言することはできません。

```js
// THIS WILL CAUSE AN ERROR
function f() {}
const f = 5;

// この場合もエラーが発生
function f() {
  const g = 5;
  var g;

  // ここには文が来る
}
```

しかし、`const` は *再代入* を防止しますが、*変更* は防止しません。定数が代入されたオブジェクトのプロパティは保護されず、以下の文は問題なく実行できます。

```js
const MY\_OBJECT = { key: "value" };
MY\_OBJECT.key = "otherValue";
```

また、配列の中身は保護されませんので、以下の文は問題なく実行できます。

```js
const MY\_ARRAY = ["HTML", "CSS"];
MY\_ARRAY.push("JAVASCRIPT");
console.log(MY\_ARRAY); // ['HTML', 'CSS', 'JAVASCRIPT'];
```

データ構造とデータ型
----------

### データ型

最新の ECMAScript 標準では、以下の 8 つのデータ型が定義されています。

* プリミティブ型のデータ型が 7 つあります。
    1. Boolean （論理値）。`true` または `false`。
    2. null。null 値を意味する特殊なキーワードです。（JavaScript は大文字・小文字を区別するため、`null` は `Null` や `NULL` などと同じではありません。）
    3. undefined （未定義）。値が未定義の最上位プロパティです。
    4. Number （数値）。整数または浮動小数点数。例えば `42` や `3.14159` など。
    5. BigInt （長整数）。精度が自由な整数値。例えば `9007199254740992n` など。
    6. String （文字列）。テキストの値を表す連続した文字。"Howdy" など。
    7. Symbol （シンボル）。インスタンスが固有で不変となるデータ型。
* そして Object （オブジェクト）。

このようにデータ型の種類は比較的少ないですが、アプリケーションで有益な演算を実行することができます。整数と実数の間に明確な違いはありません。関数もこの言語の基本的な要素です。関数は厳密にはオブジェクトの一種であり、オブジェクトは値を収める名前付きコンテナーとして、関数はスクリプトを実行可能にする手続きとして考えることができます。

### データ型の変換

JavaScript は *動的型付け* 言語です。そのため変数宣言時にデータ型を指定する必要がなく、またスクリプト実行時に必要に応じてデータ型が自動的に変換されます。

例えば以下のように変数を定義したとします。

```js
let answer = 42;
```

その後、同じ変数に文字列を代入できます。

```js
answer = "Thanks for all the fish!";
```

JavaScript は動的型付け方式であるため、この代入を行ってもにエラーメッセージは表示されません。

### 数値と '+' 演算子

数値と文字列を `+` 演算子で結合する式では、JavaScript は数値を文字列に変換します。以下の文を見てみましょう。

```js
x = "答えは " + 42; // "答えは 42"
y = 42 + " が答え"; // "42 が答え"
z = "37" + 7; // "377"
```

それ以外の演算子がある式では、JavaScript は数値を文字列に変換*しません*。例えば以下のようになります。

```js
"37" - 7; // 30
"37" \* 7; // 259
```

### 文字列から数値への変換

数値を表す値が文字列として記憶されている場合、それを変換するメソッドがあります。

* `parseInt()`
* `parseFloat()`

`parseInt` は整数のみを返すので、小数は切り捨てられます。

**メモ:** さらに、`parseInt` を使う最も良い方法は、常に基数を引数に含めるようにすることです。基数の引数は使用されている*基数*法を指定するのに使われます。

```js
parseInt("101", 2); // 5
```

文字列から数値を取り出す代替手段は、`+` (単項プラス) 演算子を使う方法です。

```js
"1.1" + "1.1"; // "1.11.1"
(+"1.1") + (+"1.1"); // 2.2
// 注: 括弧は明確さのために追加したもので、必須ではありません
```

リテラル
----

JavaScript では値の表現に *リテラル* を使います。これらは固定値であり変数ではなく、スクリプト中に直接*記述*します。この節では、以下のリテラルについて説明します。

* 配列リテラル
* 論理値リテラル
* 数値リテラル
* オブジェクトリテラル
* 正規表現リテラル
* 文字列リテラル
### 配列リテラル

配列リテラルとは、0 個以上の式のリストであり、各々の式は配列の要素を表し、角括弧 (`[]`) で括られているもののことです。配列リテラルを用いて配列を作成すると、指定された値が要素として初期化され、また配列の長さ (`length`) は指定された引数の個数に設定されます。

以下の例では 3 つの要素を持ち、配列 `coffees` を長さ (`length`) 3 で作成します。

```js
const coffees = ["French Roast", "Colombian", "Kona"];
```

最上位のスクリプト内でリテラルを用いて配列を作成した場合、JavaScript は配列リテラルを含む式を評価するたびに配列を解釈します。さらに関数内で使用されたリテラルは、関数が呼び出されるたびに生成されます。

**メモ:** 配列リテラルは `Array` オブジェクトを生成します。`Array` オブジェクトの詳細は `Array` とインデックス付きコレクションをご覧ください。

#### 配列リテラルでの余分なカンマ

配列のリテラルでカンマを 2 つ並べた場合、配列は指定されていない要素のために空のスロットを残します。以下の例では、 `fish` 配列を作成しています。

```js
const fish = ["Lion", , "Angel"];
```

この配列をログ出力すると、次のようになります。

```js
console.log(fish);
// [ 'Lion', <1 empty item>, 'Angel' ]
```

2 つ目のアイテムは "empty" であり、実際の `undefined` 値と全く同じではないことに注意してください。`Array.prototype.map` のような配列の走査メソッドを使用する場合、空のスロットはスキップされます。しかし、インデックスにアクセスする `fish[1]` は `undefined` を返します。

要素のリストの最後にカンマを付けた場合、そのカンマは無視されます。

次の例では、配列の長さ (`length`) は 3 です。`myList[3]` は存在しません。リスト内の他のカンマはすべて、新しい要素を示します。

```js
const myList = ["home", , "school", ];
```

次の例では、配列の長さ (`length`) は 4 になります。`myList[0]` と `myList[2]` が抜けています。

```js
const myList = [, "home", , "school"];
```

次の例では、配列の長さ (`length`) は 4 です。`myList[1]` と `myList[3]` が抜けています。最後のカンマのみが無視されます。

```js
const myList = ["home", , "school", ,];
```

**メモ:** 末尾のカンマは、複数行の配列を保有するときに git diff をきれいに保つのに役立ちます。なぜなら、項目を最後に追加しても一行追加するだけで、前の行は変更されないからです。

```diff
const myList = [
  "home",
  "school",
+ "hospital",
];
```

余分なカンマの動作を理解することは、言語としての JavaScript を理解するために重要です。

しかし、自分自身でコードを書くときには、足りない要素を明示的に `undefined` と宣言するか、少なくともその不在を強調するコメントを挿入する必要があります。そうすることで、コードがより明確になり、保守性も高まります。

```js
const myList = ["home", /\* 空 \*/, "school", /\* 空 \*/, ];
```

### 論理値リテラル

論理型は 2 つのリテラル値、`true` と `false` があります。

**メモ:** プリミティブの論理型である `true` や `false` と、`Boolean` オブジェクトの `true` や `false` という値とを混同してはいけません。

Boolean オブジェクトは、プリミティブの論理型のラッパーです。詳細は `Boolean` を参照してください。

### 数値リテラル

JavaScript で数値リテラルには、様々な形の整数リテラルと、基数 10 の浮動小数点数が含まれます。

言語仕様では、数値リテラルは符号なしであることが要求されていることに注意してください。どのみち、`-123.4`のようなコードは、単項の `-` 演算子を数値リテラル `123.4` に適用したものとして解釈されるため、問題ありません。

#### 整数リテラル

整数および `BigInt` 型は、10 進数、16 進数、8 進数、2 進数で書くことができます。

* *10 進数* の整数リテラルは、先頭が `0` （ゼロ）ではない一連の数字で構成されます。
* 先頭に `0` （ゼロ）である整数リテラル、または先頭の `0o` （または `0O`）は *8 進数*を示します。8 進数の数値には、`0` から `7` の数字のみが使用できます。
* 先頭の `0x` （または `0X`）は、*16 進数*の整数リテラルであることを意味します。16 進数の数値は数字 (`0` から `9`) と `a` から `f` および `A` から `F` のアルファベットで構成されます。（大文字小文字の違いは値には影響しません。たとえば `0xa` = `0xA` = `10` で `0xf` = `0xF` = `15` です。）
* 先頭の `0b` （または `0B`）は、*2 進数*の整数リテラルを表します。2 進数の数値は `0` と `1` の数字のみで構成されます。
* 整数リテラルの末尾に `n` の接尾辞を付けると、 `BigInt` リテラルを表します。この整数リテラルは上記のどの基数も使用することができます。`0123n` のような先頭が 0 の 8 進数の構文は許されませんが、 `0o123n` は問題ありません。

数値リテラルの例は以下のようになります。
```

0, 117, 123456789123456789n             （10 進数）
015, 0001, 0o777777777777n              （8 進数）
0x1123, 0x00111, 0x123456789ABCDEFn     （16 進数）
0b11, 0b0011, 0b11101001010101010101n   （2 進数）
```

詳しい情報は、字句文法リファレンスの数値リテラルをご覧ください。

### 浮動小数点リテラル

浮動小数点リテラルは、以下の部分で構成されます。

* 符号なしの 10 進数の整数部
* 小数点 (`.`)
* 小数部（残りの 10 進数）
* 指数部

指数部は、`e` または `E` の後に、符号（`+` または `-`）を先行させることできる整数が続く形になります。浮動小数点数リテラルは少なくとも 1 つの数字と、小数点もしくは `e` （または `E`）が必要です。

より簡潔に書けば、次の形式になります。
```

[digits].[digits][(E|e)[(+|-)]digits]
```

例えば以下の通りです。

```js
3.1415926;
0.123456789;
3.1e12;
0.1e-23;
```

### オブジェクトリテラル

オブジェクトリテラルとは、プロパティ名とそれに関連付けられたオブジェクトの値との 0 個以上の組が波括弧 (`{}`) で囲まれたもので作られたリストです。

**警告:** オブジェクトリテラルを文の先頭で使わないようにしてください。 `{` がブロックの始まりと解釈されるため、エラー（または予期せぬ動作）を引き起こすことになります。

以下にオブジェクトリテラルの例を示します。`car` オブジェクトの最初の要素には `myCar` プロパティが定義され、新規文字列 `"Saturn"` が割り当てられています。2 番目の要素、`getCar` プロパティには関数 `(carTypes("Honda"))`; によって呼び出された結果が即座に割り当てられます。3 番目の要素、`special` プロパティには既存の変数 (`sales`) が使われています。

```js
const sales = "Toyota";

function carTypes(name) {
  return name === "Honda" ? name : `Sorry, we don't sell ${name}.`;
}

const car = { myCar: "Saturn", getCar: carTypes("Honda"), special: sales };

console.log(car.myCar); // Saturn
console.log(car.getCar); // Honda
console.log(car.special); // Toyota
```

さらに、数値リテラルや文字列リテラルをプロパティ名に使用したり、オブジェクトを別のオブジェクトの入れ子にすることができます。以下の例では、これらの機能を使用しています。

```js
const car = { manyCars: { a: "Saab", b: "Jeep" }, 7: "Mazda" };

console.log(car.manyCars.b); // Jeep
console.log(car[7]); // Mazda
```

オブジェクトのプロパティには空の文字列を含むあらゆる文字列が使えます。もしプロパティ名が JavaScript で有効な識別子か数値でなければ、引用符で囲む必要があります。

有効でない識別子によるプロパティ名には、ドット演算子 (`.`) を使ってアクセスできません。

```js
const unusualPropertyNames = {
  '': '空文字列',
  '!': 'バン！'
}
console.log(unusualPropertyNames.'');   // SyntaxError: Unexpected string
console.log(unusualPropertyNames.!);    // SyntaxError: Unexpected token !
```

代わりに、これらはブラケット記法 (`[]`) でアクセスする必要があります。

```js
console.log(unusualPropertyNames[""]); // 空文字列
console.log(unusualPropertyNames["!"]); // バン!
```

#### 拡張オブジェクトリテラル

オブジェクトリテラルは、構築時のプロトタイプの設定、`foo: foo` 形式の短縮表記の値割り当て、メソッドの定義、`super` の呼び出し、式によるプロパティ名の計算など、様々な略記構文に対応しています。

同時に、オブジェクトリテラルとクラス定義が近くなり、オブジェクトベースの設計でも同じ利便性の一部から利益を得ることができます。

```js
const obj = {
  // \_\_proto\_\_
  \_\_proto\_\_: theProtoObj,
  // 短い 'handler: handler' の形式
  handler,
  // メソッド
  toString() {
    // スーパークラスの呼び出し
    return "d " + super.toString();
  },
  // 計算による（動的な）プロパティ名
  ["prop\_" + (() => 42)()]: 42,
};
```

### 正規表現リテラル

正規表現リテラル（後で詳しく定義）は、スラッシュで囲まれたパターンです。以下は正規表現リテラルの例です。

```js
const re = /ab+c/;
```

### 文字列リテラル

文字列リテラルとは、0 文字以上の文字を二重引用符 (`"`) または単一引用符 (`'`) で括ったものです。文字列は同じ種類の引用符で括らなければなりません (つまり、どちらも単一引用符にするか、またはどちらも二重引用符にするかです)。

以下が文字列リテラルの例です。

```js
'foo';
"bar";
'1234';
'one line \n another line';
"Joyo's cat";
```

特に `String` オブジェクトを使用する必要がない限り、文字列リテラルを使用してください。 `String` オブジェクトの詳細については、`String` を参照してください。

文字列リテラルを持つ値は、`String` オブジェクトのあらゆるメソッドを呼び出すことができます。JavaScript は自動的に文字列リテラルを一時的な String オブジェクトに変換し、メソッドを呼び出して、その後一時的に作られた String オブジェクトを破棄します。`length` プロパティを文字列リテラルで用いることもできます。

```js
// ホワイトスペースを含む文字列の文字の数を出力する。
console.log("Joyo's cat".length); // この場合は 10 が出力される。
```

テンプレートリテラルも利用することができます。テンプレートリテラルは、二重引用符や単一引用符の代わりに逆引用符 (```) (grave accent) で囲まれたものです。

テンプレート文字列は文字列の構築に糖衣構文を利用することができます。（これは Perl や Python などの文字列補完機能に似ています。）

```js
// 基本的な文字列リテラルの作成
`In JavaScript '\n' is a line-feed.`;

// 複数行の文字列
`In JavaScript, template strings can run
 over multiple lines, but double and single
 quoted strings cannot.`;

// 文字列補完
const name = "Lev",
  time = "today";
`Hello ${name}, how are you ${time}?`;
```

タグ付きテンプレートは、テンプレートリテラルを指定するためのコンパクトな構文と、それを解釈するための「タグ」関数の呼び出しを組み合わせたものです。タグ付きテンプレートは、文字列と関連する値の集合を処理する関数を呼び出すための、より簡潔で意味づけされた方法にすぎません。以下の例では、テンプレートタグ関数の名前が `print` であり、テンプレートタグ関数の名前がテンプレートリテラルの前にあります。`print` 関数は引数を補間し、オブジェクトや配列をシリアライズするので、厄介な `[object Object]` になることを避けることができます。

```js
const formatArg = (arg) => {
  if (Array.isArray(arg)) {
    // Print a bulleted list
    return arg.map((part) => `- ${part}`).join("\n");
  }
  if (arg.toString === Object.prototype.toString) {
    // This object will be serialized to "[object Object]".
    // Let's print something nicer.
    return JSON.stringify(arg);
  }
  return arg;
};

const print = (segments, ...args) => {
  // For any well-formed template literal, there will always be N args and
  // (N+1) string segments.
  let message = segments[0];
  segments.slice(1).forEach((segment, index) => {
    message += formatArg(args[index]) + segment;
  });
  console.log(message);
};

const todos = [
  "Learn JavaScript",
  "Learn Web APIs",
  "Set up my website",
  "Profit!",
];

const progress = { javascript: 20, html: 50, css: 10 };

print`I need to do:
${todos}
My current progress is: ${progress}
`;

// I need to do:
// - Learn JavaScript
// - Learn Web APIs
// - Set up my website
// - Profit!
// My current progress is: {"javascript":20,"html":50,"css":10}
```

タグ付きテンプレートリテラルは、関数呼び出しの糖衣構文に過ぎないので、上記を同等の関数呼び出しとして書き直すことができます。

```js
print(["I need to do:\n", "\nMy current progress is: ", "\n"], todos, progress);
```

これは `console.log` スタイルの補間を連想させるかもしれません。

```js
console.log("I need to do:\n%o\nMy current progress is: %o\n", todos, progress);
```

タグ付きテンプレートは、変数とテンプレート自体を別個に宣言しなければならない従来の「フォーマッター」関数よりも、より自然に読み取れることがおわかりいただけると思います。

#### 文字列での特殊文字の使用

文字列では、通常の文字に加えて特殊文字も使用できます。次の例をご覧ください。

```js
"one line \n another line";
```

ここで、JavaScript の文字列で使用できる特殊文字の表を示します。

| 文字 | 意味 |
| --- | --- |
| `\0` | ヌル文字 |
| `\b` | バックスペース |
| `\f` | 改ページ |
| `\n` | 改行 |
| `\r` | 復帰 |
| `\t` | タブ |
| `\v` | 垂直タブ |
| `\'` | アポストロフィまたは単一引用符 |
| `\"` | 二重引用符 |
| `\\` | バックスラッシュ (\) |
| `\XXX` | `0` から `377` までの 3 桁の 8 進数 *XXX* で指定された、Latin-1 エンコーディングの文字。 例えば、`\251` は著作権記号を示します。 |
|  |  |
| `\xXX` | `00` から `FF` までの 2 桁の 16 進数 *XX* で指定された、Latin-1 エンコーディングの文字。 例えば、`\xA9` は著作権記号を示します。 |
|  |  |
| `\uXXXX` | 4 桁の 16 進数 *XXXX* で指定された Unicode 文字。 例えば、`\u00A9` は著作権記号を示します。Unicode エスケープシーケンスをご覧ください。 |
| `\u{XXXXX}` | Unicode コードポイントエスケープです。 例えば `\u{2F804}` は単純な Unicode エスケープである `\uD87E\uDC04` と同じです。 |

#### 文字のエスケープ

上記の表に掲載されていない文字は直前にバックスラッシュをつけても無視されますが、こうした使い方は非推奨であり使用を避けるべきです。

バックスラッシュを直前につけることで、引用符を文字列に含めることができます。これは引用符の*エスケープ*と呼ばれます。例えば以下のようにします。

```js
const quote = "He read \"The Cremation of Sam McGee\" by R.W. Service.";
console.log(quote);
```

この結果は次のようになります。
```

He read "The Cremation of Sam McGee" by R.W. Service.
```

文字列にバックスラッシュそのものを含めるには、バックスラッシュのエスケープが必要です。例えば、文字列に `c:\temp` というファイルパスを代入するには、以下のようにします。

```js
const home = "c:\\temp";
```

改行の直前にバックスラッシュを置くことで、改行をエスケープすることもできます。バックスラッシュと改行の両方が、文字列の値から取り除かれます。

```js
const str =
  "this string \
is broken \
across multiple \
lines.";
console.log(str); // この文字列は複数行にわたって分解されます。
```

関連情報
----

本章では宣言とデータ型についての基本文法に重点を置いています。JavaScript の言語構成についてより詳しく知りたければ、当ガイドの以下に挙げた章をご覧ください。

* 制御フローとエラー処理
* ループと反復処理
* 関数
* 式と演算子

次章では、制御フローの構造とエラー処理について見ていきます。

* « 前のページ
* 次のページ »


アサーション - JavaScript

アサーション
======

アサーションには、 行や単語の先頭・末尾を示す境界や、（先読み、後読み、条件式を含む）何らかの方法で照合が可能なことを示す、その他のパターンが含まれます。

試してみましょう
--------

種類
--

### 境界型のアサーション

| 文字 | 意味 |
| --- | --- |
| `^` |
 入力の先頭に一致します。複数行フラグが true
 にセットされている場合は、改行文字の直後にも一致します。例えば
 `/^A/` は "an A" の 'A' には一致しませんが、"An E" の 'A'
 には一致します。

**メモ:** この文字は、文字クラスパターンの先頭にある場合は異なる意味を持ちます。
 |
| `$` |
 入力の末尾に一致します。複数行フラグが true
 にセットされている場合は、改行文字の直前にも一致します。例えば
 `/t$/` は "eater" の "t" には一致しませんが、"eat" の "t"
 には一致します。
  |
| `\b` |
 単語の区切りに一致します。これは、単語構成文字と後に続く非単語構成文字の間、または非単語構成文字と後に続く単語構成文字の間です。単語の区切りは一致する「文字」ではありません。アンカーのように、単語の区切りは一致した部分に含まれません。言い換えると、一致した単語の区切りの長さは
 0 です。

例:* `/\bm/` は "moon" の "m" に一致します。
* `/oo\b/` は "moon" の "oo" に一致しません。これは "oo" の 後に単語構成文字である "n" が続いているためです。
* `/oon\b/` は "moon" の "oon"
 に一致します。これは、文字列の終端であって、後に単語構成文字が続いていないためです。
* `/\w\b\w/` はどこにも一致しないでしょう。単語構成文字の後に非単語構成文字と単語構成文字の両方が続くことはありえないからです。

バックスペース文字 (`[\b]`) については文字クラスを見てください。 |
| `\B` | 単語の区切り以外に一致します。これは、前の文字と次の文字が同じ種類である位置のことです。2 つの文字の間や 2 つの空白の間など、どちらも単語構成文字か、あるいはどちらも非単語構成文字でなければなりません。文字列の先頭と末尾は、非単語構成文字とみなされます。一致した単語の区切りと同じように、一致した非単語の区切りも一致に含まれません。例えば、 `/\Bon/` は "at noon" の "on" に、 `/ye\B/` は "possibly yesterday" の "ye" に一致します。 |

### その他のアサーション

**メモ:** `?` の文字は数量詞としても使用されます。

| 文字 | 意味 |
| --- | --- |
| `x(?=y)` | **先読みアサーション:** "x" の後に "y" が続く場合のみ "x" に一致します。例えば、`/Jack(?=Sprat)/` は "Jack" の後に "Sprat" が続く場合のみ一致します。`/Jack(?=Sprat|Frost)/` は "Jack" の後に "Sprat" または "Frost" が続く場合のみ一致します。しかし、 "Sprat" も "Frost" も一致した結果には含まれません。 |
| `x(?!y)` | **否定先読みアサーション:** "x" の後に "y" が続いていない場合のみ "x" に一致します。例えば、 `/\d+(?!\.)/` は数字の後に小数点が続かない場合のみ一致します。`/\d+(?!\.)/.exec('3.141')`は "141" には一致しますが、 "3" には一致しません。 |
| `(?<=y)x` | **後読みアサーション:** "x" の前に "y" がある場合のみ "x" に一致します。例えば、`/(?<=Jack)Sprat/` は、 "Jack" が先行する場合のみ、 "Sprat" に一致します。 `/(?<=Jack|Tom)Sprat/` は、 "Jack" か "Tom" が先行する場合のみ、 "Sprat" に一致します。しかし、 "Jack" も "Tom" も一致した結果には含まれません。 |
| `(?<!y)x` | **否定後読みアサーション:** "x" の前に "y" がない場合のみ "x" に一致します。例えば、 `/(?<!-)\d+/` は、数字の前にマイナス記号がない場合のみ、数字に一致します。 `/(?<!-)\d+/.exec('3')` は "3" に一致します。 `/(?<!-)\d+/.exec('-3')` では数字の前にマイナス記号があるため、一致するものは見つかりません。 |

例
-

### 基本的な境界型の例

```js
// おかしい文字列を修正するために正規表現の境界を利用します。
buggyMultiline = `tey, ihe light-greon apple
tangs on ihe greon traa`;

// 1) 文字列の最初と改行の直後の一致を修正するために ^ を利用します。
buggyMultiline = buggyMultiline.replace(/^t/gim, "h");
console.log(1, buggyMultiline); // 'tey', 'tangs' を 'hey', 'hangs' に修正します。 'traa' は対象外です。

// 2) テキストの末尾を修正するために $ を利用します。
buggyMultiline = buggyMultiline.replace(/aa$/gim, "ee.");
console.log(2, buggyMultiline); // 'traa' を 'tree' に修正します。

// 3) 単語と空白の間の境界の右の文字に一致させるために \b を利用します。
buggyMultiline = buggyMultiline.replace(/\bi/gim, "t");
console.log(3, buggyMultiline); // 'ihe' を修正しますが、'light'は対象外です。

// 4) エンティティの境界内の文字に一致するために \B を利用します。
fixedMultiline = buggyMultiline.replace(/\Bo/gim, "e");
console.log(4, fixedMultiline); // 'greon' を修正しますが、'on' は対象外です。
```

### ^ 制御文字を利用した入力の先頭との照合

`^` は、通常、入力の先頭に一致させるために利用します。この例では、`/^A/` という正規表現で 'A' で始まるフルーツを取得します。ここでの `^` は、入力の先頭を示すという、たった 1 つの役割を果たしています。適切なフルーツを選択するために filter メソッドとアロー関数を用います。

```js
const fruits = ["Apple", "Watermelon", "Orange", "Avocado", "Strawberry"];

// /^A/ 正規表現で 'A' で始まるフルーツを選択します。
// ここでの'^' 制御記号は「入力の先頭に一致する」という 1 つの役割だけで利用されています。

const fruitsStartsWithA = fruits.filter((fruit) => /^A/.test(fruit));
console.log(fruitsStartsWithA); // [ 'Apple', 'Avocado' ]
```

2 番目の例での `^` は、入力の先頭への一致と、文字クラスで用いられた場合の文字集合の否定または補集合という、両方で利用されています。

```js
const fruits = ["Apple", "Watermelon", "Orange", "Avocado", "Strawberry"];

// /^[^A]/ という正規表現で 'A' で始まらないフルーツを選択します。
// この例では、'^' 制御記号は 2 つの意味を表しています。
// 1) 入力の先頭に一致
// 2) [^A] という文字集合の否定または補集合
// つまり、角括弧で囲まれた中にないあらゆるものに一致します。

const fruitsStartsWithNotA = fruits.filter((fruit) => /^[^A]/.test(fruit));

console.log(fruitsStartsWithNotA); // [ 'Watermelon', 'Orange', 'Strawberry' ]
```

### 単語の境界に一致

```js
const fruitsWithDescription = ["Red apple", "Orange orange", "Green Avocado"];

// 単語の終わりに 'en' または 'ed' を含む記述を選択します。
const enEdSelection = fruitsWithDescription.filter((descr) =>
  /(en|ed)\b/.test(descr),
);

console.log(enEdSelection); // [ 'Red apple', 'Green Avocado' ]
```

### 先読みアサーション

```js
// JS 先読みアサーション x(?=y)

const regex = /First(?= test)/g;

console.log("First test".match(regex)); // [ 'First' ]
console.log("First peach".match(regex)); // null
console.log("This is a First test in a year.".match(regex)); // [ 'First' ]
console.log("This is a First peach in a month.".match(regex)); // null
```

### 基本的な否定先読みアサーション

例えば、`/\d+(?!\.)/` は小数点が後に続かない数値にだけ一致します。`/\d+(?!\.)/.exec('3.141')` は "141" に一致しますが、 "3" には一致しません。

```js
console.log(/\d+(?!\.)/g.exec("3.141")); // [ '141', index: 2, input: '3.141' ]
```

### アサーションと範囲における '?!' の組み合わせの異なる意味での利用

`?!` の組み合わせを利用するとき、アサーション（`/x(?!y)/` など）と文字クラス （`[^?!]` など）では異なる意味を持ちます。

```js
const orangeNotLemon =
  "Do you want to have an orange? Yes, I do not want to have a lemon!";

// アサーション /x(?!y)/ と範囲 /[^?!]/ では '?!' の組み合わせの利用は異なる意味を持ちます。
const selectNotLemonRegex = /[^?!]+have(?! a lemon)[^?!]+[?!]/gi;
console.log(orangeNotLemon.match(selectNotLemonRegex)); // [ 'Do you want to have an orange?' ]

const selectNotOrangeRegex = /[^?!]+have(?! an orange)[^?!]+[?!]/gi;
console.log(orangeNotLemon.match(selectNotOrangeRegex)); // [ ' Yes, I do not want to have a lemon!' ]
```

### 後読みアサーション

```js
const oranges = ["ripe orange A ", "green orange B", "ripe orange C"];

const ripeOranges = oranges.filter((fruit) => fruit.match(/(?<=ripe )orange/));
console.log(ripeOranges); // [ 'ripe orange A ', 'ripe orange C' ]
```

関連情報
----

* 正規表現ガイド
    + 文字クラス
    + 数量詞
    + Unicode プロパティエスケープ
    + グループと後方参照
* `RegExp()` コンストラクター
* ECMAScript 仕様書でのアサーション（英語）


数量詞 - JavaScript

数量詞
===

数量詞は、一致させる文字や式の数を示します。

試してみましょう
--------

種類
--

**メモ:** 以下の表の中で、*アイテム*は単一の文字だけでなく、文字クラス、Unicode プロパティエスケープ、グループと後方参照を示すこともあります。

| 文字 | 意味 |
| --- | --- |
| `*x**` |
 直前のアイテム "x" の 0 回以上の繰り返しに一致します。例えば
 `/bo*/` は "A ghost booooed" の "boooo" や "A bird warbled"
 の "b" に一致しますが、 "A goat grunted" には一致しません。
  |
| `*x*+` |
 直前のアイテム "x" の 1 回以上の繰り返しに一致します。`{1,}`
 と同等です。例えば `/a+/` は "candy" の "a" や
 "caaaaaaandy" のすべての "a" に一致します。
  |
| `*x*?` |
 直前のアイテム "x" の 0 回か 1 回の出現に一致します。例えば
 `/e?le?/` は "angel" の "el" や "angle" の "le"
 に一致します。

`*`、`+`、`?`、`{}` といった数量詞の直後に使用した場合、既定とは逆に、その数量詞を非貪欲（出現回数が最小のものに一致）とします。既定は貪欲（出現回数が最大のものに一致）です。 |
| `*x*{*n*}` | "n" には正の整数が入ります。直前のアイテム "x" がちょうど "n" 回出現するものに一致します。例えば `/a{2}/` は "candy" の "a" には一致しませんが、"caandy" のすべての "a"、"caaandy" の最初の 2 つの "a" に一致します。 |
| `*x*{*n*,}` |
 "n" には正の整数が入ります。直前のアイテム "x" の少なくとも "n"
 回の出現に一致します。例えば、`/a{2,}/` は "candy" の "a"
 には一致しませんが、"caandy" や "caaaaaaandy" の "a"
 のすべてに一致します。
  |
| `*x*{*n*,*m*}` |
 "n" には 0 と正の整数が、 "m" には "n"
 より大きい正の整数が入ります。直前のアイテム "x" が少なくとも "n"
 回、多くても "m" 回出現するものに一致します。例えば
 `/a{1,3}/` は "cndy" では一致せず、"candy" の 'a'、"caandy"
 の 最初の 2 個の "a"、"caaaaaaandy" の最初の 3 個の "a"
 に一致します。"caaaaaaandy" では元の文字列に "a" が 4
 個以上ありますが、一致するのは "aaa" であることに注意してください。
  |
| `*x**?``*x*+?``*x*??``*x*{n}?``*x*{n,}?``*x*{n,m}?` | 既定では `*` や `+` といった数量詞は貪欲です。つまり、できる限り多くの文字列と一致しようとします。数量詞の後に `?` の文字を指定すると、数量詞が「非貪欲」になります。つまり、一致が見つかるとすぐに停止します。例えば、"some <foo> <bar> new </bar> </foo> thing" といった文字列が与えられた場合は、* `/<.*>/` は "<foo> <bar> new </bar> </foo>" に一致します。
* `/<.*?>/` は "<foo>" に一致します。
 |

例
-

### 繰り返しパターン

```js
const wordEndingWithAs = /\w+a+\b/;
const delicateMessage = "This is Spartaaaaaaa";

console.table(delicateMessage.match(wordEndingWithAs)); // [ "Spartaaaaaaa" ]
```

### 文字数

```js
const singleLetterWord = /\b\w\b/g;
const notSoLongWord = /\b\w{2,6}\b/g;
const loooongWord = /\b\w{13,}\b/g;

const sentence = "Why do I have to learn multiplication table?";

console.table(sentence.match(singleLetterWord)); // ["I"]
console.table(sentence.match(notSoLongWord)); // [ "Why", "do", "have", "to", "learn", "table" ]
console.table(sentence.match(loooongWord)); // ["multiplication"]
```

### 省略可能な文字

```js
const britishText = "He asked his neighbour a favour.";
const americanText = "He asked his neighbor a favor.";

const regexpEnding = /\w+ou?r/g;
// \w+ 1 つ以上の文字
// o "o" が続く
// u? 省略可能で "u" が続く
// r "r" が続く

console.table(britishText.match(regexpEnding));
// ["neighbour", "favour"]

console.table(americanText.match(regexpEnding));
// ["neighbor", "favor"]
```

### 貪欲と非貪欲

```js
const text = "I must be getting somewhere near the center of the earth.";
const greedyRegexp = /[\w ]+/;
// [\w ] ラテンアルファベットまたは空白
// + 1 回以上

console.log(text.match(greedyRegexp)[0]);
// "I must be getting somewhere near the center of the earth"
// テキストのすべてに一致 (ピリオドを除く)

const nonGreedyRegexp = /[\w ]+?/; // クエスチョンマークに注目
console.log(text.match(nonGreedyRegexp));
// "I"
// 一致する箇所は取りうる最も短い 1 文字
```

関連情報
----

* 正規表現ガイド
    + 文字クラス
    + アサーション
    + Unicode プロパティエスケープ
    + グループと後方参照
* `RegExp()` コンストラクター
* ECMAScript 仕様書の数量詞（英語）


文字クラス - JavaScript

文字クラス
=====

文字クラスは、文字や数字の区別など、文字の種類を区別します。

試してみましょう
--------

種類
--

| 文字 | 意味 |
| --- | --- |
| `[xyz][a-c]` | 文字クラス。囲んだ文字のいずれかに一致します。ハイフンを使用して文字の範囲を指定することもできますが、ハイフンが角括弧で囲まれた最初または最後の文字として現れた場合、それは通常の文字として文字クラスに含めるためのリテラルハイフンと見なされます。

 例えば、 `[abcd]` は `[a-d]` と同じです。
 "brisket" の "b" や "chop" の "c" に一致します。

例えば、 `[abcd-]` と `[-abcd]` は "brisket" の "b"、 "chop" の "c"、そして "non-profit" の "-" （ハイフン）に一致します。
例えば、 `[\w-]` は `[A-Za-z0-9_-]` と同じです。どちらも "brisket" の "b"、 "chop" の "c"、 "non-profit" の "n" に一致します。 |
| `[^xyz][^a-c]` | 否定または補完する文字クラス。つまり、括弧で囲まれていないもの全てに一致します。ハイフンを使用して文字の範囲を指定することができますが、ハイフンが `^` の後の最初の文字、または角括弧で囲まれた最後の文字として現れた場合、 それは通常の文字として文字クラスに含めるためにリテラルハイフンと解釈されます。例えば、`[^abc]` は `[^a-c]` と同じです。これらは、最初は "bacon" の "o" や "chop" の "h" に一致します。

**メモ:** ^ の文字は入力の先頭も意味することがあります。
 |
| `.` | 次のいずれかの意味を持ちます。* 改行文字 (`\n`、`\r`、`\u2028`、`\u2029`) を除くあらゆる 1 文字と一致します。例えば、`/.y/` は "my" と "ay" に一致し、"yes make my day" の "yes" には一致しません。
* 文字クラス内では `.` はその特別な意味を失い、文字通りの "." と一致します。

複数行フラグ (`m`) は "." の意味を変えないことに注意してください。そのため、複数行にわたるパターンに一致させるには、（IE の古いバージョン以外なら）文字集合 `[^]` を使うことで、改行を含む任意の文字に一致します。
`s` "dotAll" フラグは、ドットが改行文字に一致できるようにします。 |
| `\d` | あらゆる（アラビア）数字に一致します。`[0-9]` に相当します。例えば `/\d/` や `/[0-9]/` は "B2 is the suite number" の "2" に一致します。 |
| `\D` | あらゆる（アラビア）数字以外の文字に一致します。`[^0-9]` に相当します。例えば `/\D/` や `/[^0-9]/` は "B2 is the suite number" の "B" に一致します。 |
| `\w` | アンダースコアを含むあらゆる半角英数字（基本ラテンアルファベット）に一致します。 `[A-Za-z0-9_]` に相当します。例えば `/\w/` は、"apple" の "a"、"$5.28" の "5"、"3D" の "3" に一致します。 |
| `\W` | 基本ラテンアルファベットの文字以外に一致します。 `[^A-Za-z0-9_]` と同等です。例えば `/\W/` や `/[^A-Za-z0-9_]/` は、"50%" の "%" や "Émanuel" の "É" に一致します。 |
| `\s` | ホワイトスペース 1 文字に一致します。例えば空白、タブ、改ページ、改行、その他の Unicode 空白文字などです。 `[\f\n\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]` に相当します。例えば `/\s\w*/` は "foo bar" の " bar" に一致します。 |
| `\S` | ホワイトスペース以外の 1 文字に一致します。`[^
\f\n\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]` に相当します。例えば `/\S\w*/` は "foo bar" の "foo" に一致します。 |
| `\t` | 水平タブに一致します。 |
| `\r` | 復帰文字に一致します。 |
| `\n` | 行送り文字に一致します。 |
| `\v` | 垂直タブに一致します。 |
| `\f` | 改ページに一致します。 |
| `[\b]` | 後退文字に一致します。単語境界文字 (`\b`) を探す場合はアサーションを参照してください。 |
| `\0` | NUL 文字に一致します。この後ろに他の数字を続けてはいけません。 |
| `\c*X*` |
キャレット記法を使用した制御文字に一致します。 "X" には A–Z の文字が入ります（コードポイント`U+0001`*–*`U+001A` に対応します）。例えば
 `/\cM\J/` は "\r\n" に一致します。
  |
| `\x*hh*` | `*hh*` （2 桁の 16 進数）コードからなる文字に一致します。 |
| `\u*hhhh*` | `*hhhh*` （4 桁の 16 進数）の値からなる UTF-16 コードユニットに一致します。 |
| `\u*{hhhh}*` または `*\u{hhhhh}*` | （`u` フラグがセットされた時のみ） `U+*hhhh*` または `U+*hhhhh*` (16 進数) Unicode 値からなる文字に一致します。 |
| `\p{*UnicodeProperty*}`,
 `\P{*UnicodeProperty*}` | Unicode 文字プロパティ に基づいて照合します（例えば、絵文字、日本語のカタカナ文字、日本語や中国語の漢字のみに一致するようにするなど）。 |
| `\` |
 次の文字を特別に扱うこと、「エスケープ」することを示します。
 その振る舞いは、2 通りのうちのどちらか 1 つです。
 * 通常文字の前に付けられた場合、次の文字が特別なもので、文字通りには評価されないことを示します。例えば、 `/b/` は文字 `"b"` に一致します。しかし "b" の前にバックスラッシュを置いて `\b` とすると、単語区切りを意味するようになります。
* 特殊文字の前に付けられた場合、次の文字が特別なものでなく、文字通りに評価されることを表します。例えば、 "\*" は、直前の文字が 0 個以上の出現した場合に一致することを意味する特殊文字です。例えば、 `/a*/` は 0 個以上の "a" と一致します。 `*` と文字通りに照合するには、その直前にバックスラッシュを入れます。例えば、`/a\*/` は "a\*" と一致します。

この文字を文字通りに一致させるには、それ自身をエスケープします。つまり、 `\` を検索するには `/\\/` を使ってください。
 |
| `*x*|*y*` | **論理和:** "x" または "y" に一致します。パイプ (`|`) で区切られた各成分は、代替 (*alternative*)と呼ばれます。例えば、`/green|red/` は "green apple" の "green" と "red apple" の "red" に一致します。````**メモ:** 論理和は「選択肢の集合」を指定するもう一つの方法ですが、文字クラスではありません。論理和は独立したものではありません。大きなパターンの一部にするためにはグループを使用する必要があります。`[abc]` は機能的には `(?:a|b|c)` と等価です。`` |

例
-

### 一連の数字を探す

```js
const randomData = "015 354 8787 687351 3512 8735";
const regexpFourDigits = /\b\d{4}\b/g;
// \b は境界を示します（つまり、単語の途中から照合開始しません）
// \d{4} は 4 つの数字を示します
// \b は別の境界を示します（つまり、単語の真ん中でマッチが終わりません）

console.table(randomData.match(regexpFourDigits));
// ['8787', '3512', '8735']
```

### A から始まる（ラテンアルファベットの）単語を探す

```js
const aliceExcerpt =
  "I'm sure I'm not Ada,' she said, 'for her hair goes in such long ringlets, and mine doesn't go in ringlets at all.";
const regexpWordStartingWithA = /\b[aA]\w+/g;
// \b は境界を示します（つまり、単語の途中から照合を開始しません）
// [aA] は a または A の文字を示します
// \w+ は複数回の \*ラテンアルファベットからなる\* 任意の文字を示します

console.table(aliceExcerpt.match(regexpWordStartingWithA));
// ['Ada', 'and', 'at', 'all']
```

### （Unicode 文字の）単語を探す

単語を表すために、ラテンアルファベットではなく、 Unicode 文字の範囲を使用することができます。（つまり、ロシア語やアラビア語のような他の言語のテキストを扱うことができます。） Unicode の 「基本多言語面」には、世界中で使われているほとんどの文字が含まれており、それらの文字で書かれた単語にマッチするための文字クラスと範囲を利用できます。

```js
const nonEnglishText = "Приключения Алисы в Стране чудес";
const regexpBMPWord = /([\u0000-\u0019\u0021-\uFFFF])+/gu;
// U+0000 から U+FFFF までの BMP、ただし、U+0020 は空白

console.table(nonEnglishText.match(regexpBMPWord));
["Приключения", "Алисы", "в", "Стране", "чудес"];
```

### 母音を数える

```js
const aliceExcerpt =
  "There was a long silence after this, and Alice could only hear whispers now and then.";
const regexpVowels = /[AEIOUYaeiouy]/g;

console.log("Number of vowels:", aliceExcerpt.match(regexpVowels).length);
// Number of vowels: 26
```

関連情報
----

* 正規表現ガイド
    + アサーション
    + 数量詞
    + Unicode プロパティエスケープ
    + グループと後方参照
* `RegExp()` コンストラクター
* ECMAScript 仕様書での文字クラス（英語）


正規表現構文早見表 - JavaScript

正規表現構文早見表
=========

このページでは、RegExp ガイドの記事の内容を集約して、RegExp 構文のすべての機能を網羅した全体的な早見表を提供します。特定のトピックに関する詳細な情報が必要な場合は、対応する見出しのリンクを辿って完全な記事にアクセスするか、ガイドに移動してください。

文字クラス
-----

文字クラスは、文字の種類を判別するものです。例えば、文字と数字を判別することができます。

| 文字 | 意味 |
| --- | --- |
| `[xyz][a-c]` | 文字クラス。囲んだ文字のいずれかに一致します。ハイフンを使用して文字の範囲を指定することもできますが、ハイフンが角括弧で囲まれた最初または最後の文字として現れた場合、それは通常の文字として文字クラスに含めるためのリテラルハイフンと見なされます。

 例えば、 `[abcd]` は `[a-d]` と同じです。
 "brisket" の "b" や "chop" の "c" に一致します。

例えば、 `[abcd-]` と `[-abcd]` は "brisket" の "b"、 "chop" の "c"、そして "non-profit" の "-" （ハイフン）に一致します。
例えば、 `[\w-]` は `[A-Za-z0-9_-]` と同じです。どちらも "brisket" の "b"、 "chop" の "c"、 "non-profit" の "n" に一致します。 |
| `[^xyz][^a-c]` | 否定または補完する文字クラス。つまり、括弧で囲まれていないもの全てに一致します。ハイフンを使用して文字の範囲を指定することができますが、ハイフンが `^` の後の最初の文字、または角括弧で囲まれた最後の文字として現れた場合、 それは通常の文字として文字クラスに含めるためにリテラルハイフンと解釈されます。例えば、`[^abc]` は `[^a-c]` と同じです。これらは、最初は "bacon" の "o" や "chop" の "h" に一致します。

**メモ:** ^ の文字は入力の先頭も意味することがあります。
 |
| `.` | 次のいずれかの意味を持ちます。* 改行文字 (`\n`、`\r`、`\u2028`、`\u2029`) を除くあらゆる 1 文字と一致します。例えば、`/.y/` は "my" と "ay" に一致し、"yes make my day" の "yes" には一致しません。
* 文字クラス内では `.` はその特別な意味を失い、文字通りの "." と一致します。

複数行フラグ (`m`) は "." の意味を変えないことに注意してください。そのため、複数行にわたるパターンに一致させるには、（IE の古いバージョン以外なら）文字集合 `[^]` を使うことで、改行を含む任意の文字に一致します。
`s` "dotAll" フラグは、ドットが改行文字に一致できるようにします。 |
| `\d` | あらゆる（アラビア）数字に一致します。`[0-9]` に相当します。例えば `/\d/` や `/[0-9]/` は "B2 is the suite number" の "2" に一致します。 |
| `\D` | あらゆる（アラビア）数字以外の文字に一致します。`[^0-9]` に相当します。例えば `/\D/` や `/[^0-9]/` は "B2 is the suite number" の "B" に一致します。 |
| `\w` | アンダースコアを含むあらゆる半角英数字（基本ラテンアルファベット）に一致します。 `[A-Za-z0-9_]` に相当します。例えば `/\w/` は、"apple" の "a"、"$5.28" の "5"、"3D" の "3" に一致します。 |
| `\W` | 基本ラテンアルファベットの文字以外に一致します。 `[^A-Za-z0-9_]` と同等です。例えば `/\W/` や `/[^A-Za-z0-9_]/` は、"50%" の "%" や "Émanuel" の "É" に一致します。 |
| `\s` | ホワイトスペース 1 文字に一致します。例えば空白、タブ、改ページ、改行、その他の Unicode 空白文字などです。 `[\f\n\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]` に相当します。例えば `/\s\w*/` は "foo bar" の "bar" に一致します。 |
| `\S` | ホワイトスペース以外の 1 文字に一致します。`[^
\f\n\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]` に相当します。例えば `/\S\w*/` は "foo bar" の "foo" に一致します。 |
| `\t` | 水平タブに一致します。 |
| `\r` | 復帰文字に一致します。 |
| `\n` | 行送り文字に一致します。 |
| `\v` | 垂直タブに一致します。 |
| `\f` | 改ページに一致します。 |
| `[\b]` | 後退文字に一致します。単語境界文字 (`\b`) を探す場合はアサーションを参照してください。 |
| `\0` | NUL 文字に一致します。この後ろに他の数字を続けてはいけません。 |
| `\c*X*` |
キャレット記法を使用した制御文字に一致します。 "X" には A–Z の文字が入ります（コードポイント`U+0001`*–*`U+001A` に対応します）。例えば
 `/\cM\J/` は "\r\n" に一致します。
  |
| `\x*hh*` | `*hh*` （2 桁の 16 進数）コードからなる文字に一致します。 |
| `\u*hhhh*` | `*hhhh*` （4 桁の 16 進数）の値からなる UTF-16 コードユニットに一致します。 |
| `\u*{hhhh}*` または `*\u{hhhhh}*` | （`u` フラグがセットされた時のみ） `U+*hhhh*` または `U+*hhhhh*` (16 進数) Unicode 値からなる文字に一致します。 |
| `\` |
 次の文字を特別に扱うこと、「エスケープ」することを示します。
 その振る舞いは、2 通りのうちのどちらか 1 つです。
 * 通常文字の前に付けられた場合、次の文字が特別なもので、文字通りには評価されないことを示します。例えば、 `/b/` は文字 `"b"` に一致します。しかし "b" の前にバックスラッシュを置いて `\b` とすると、単語区切りを意味するようになります。
* 特殊文字の前に付けられた場合、次の文字が特別なものでなく、文字通りに評価されることを表します。例えば、 "\*" は、直前の文字が 0 個以上の出現した場合に一致することを意味する特殊文字です。例えば、 `/a*/` は 0 個以上の "a" と一致します。 `*` と文字通りに照合するには、その直前にバックスラッシュを入れます。例えば、`/a\*/` は "a\*" と一致します。

 なお、 `:`, `-`,
 `@`, などの一部の文字は、エスケープされたときにもエスケープされていないときにも、特別な意味を持たないことに注意してください。正規表現では `\:`, `\-`, `\@` のようなエスケープシーケンスは、エスケープされていないリテラル文字と同じになります。しかし、unicode フラグを持つ正規表現では、これらは *invalid identity escape* エラーが発生します。これは、`p`や`k`のような新しいエスケープシーケンスを使用する既存のコードとの後方互換性を確保するために行われます。

**メモ:** この文字を文字通りに一致させるには、それ自身をエスケープしてください。つまり、 `\` を検索するには `/\\/` を使ってください。
 |
| `*x*|*y*` | **論理和:** "x" または "y" に一致します。パイプ (`|`) で区切られた各成分は、代替 (*alternative*)と呼ばれます。例えば、`/green|red/` は "green apple" の "green" と "red apple" の "red" に一致します。

**メモ:** 論理和は「選択肢の集合」を指定するもう一つの方法ですが、文字クラスではありません。論理和は独立したものではありません。大きなパターンの一部にするためにはグループを使用する必要があります。`[abc]` は機能的には `(?:a|b|c)` と等価です。
 |

アサーション
------

アサーションには、行や単語の先頭と末尾を示す境目、他にも何らかの形で一致が可能であることを示すパターン（先読み、後読み、条件式など）が含まれます。

### 境界型のアサーション

| 文字 | 意味 |
| --- | --- |
| `^` |
 入力の先頭に一致します。複数行フラグが true
 にセットされている場合は、改行文字の直後にも一致します。例えば
 `/^A/` は "an A" の 'A' には一致しませんが、"An E" の 'A'
 には一致します。

**メモ:** この文字は、文字クラスパターンの先頭にある場合は異なる意味を持ちます。
 |
| `$` |
 入力の末尾に一致します。複数行フラグが true
 にセットされている場合は、改行文字の直前にも一致します。例えば
 `/t$/` は "eater" の "t" には一致しませんが、"eat" の "t"
 には一致します。
  |
| `\b` |
 単語の区切りに一致します。これは、単語構成文字と後に続く非単語構成文字の間、または非単語構成文字と後に続く単語構成文字の間、または文字列の先頭・末尾です。単語の区切りは一致する「文字」ではありません。アンカーのように、単語の区切りは一致した部分に含まれません。言い換えると、一致した単語の区切りの長さは
 0 です。

例:* `/\bm/` は "moon" の "m" に一致します。
* `/oo\b/` は "moon" の "oo" に一致しません。これは "oo" の 後に単語構成文字である "n" が続いているためです。
* `/oon\b/` は "moon" の "oon"
 に一致します。これは、文字列の終端であるためです。
* `/\w\b\w/` はどこにも一致しないでしょう。単語構成文字の後に非単語構成文字と単語構成文字の両方が続くことはありえないからです。

バックスペース文字 (`[\b]`) については文字クラスを見てください。 |
| `\B` | 単語以外の境界に一致します。これは、前の文字と次の文字が同じ種類である位置のことです。どちらも単語でなければならないか、または、 2 つの文字の間や 2 つの空白の間など、どちらも非単語でなければなりません。文字列の先頭と末尾は、非単語とみなされます。一致した単語の境界と同じように、一致した非単語の境界も一致に含まれません。例えば、 `/onBon/` は "at noon" の "on" に、 `/ye}B/` は "possibly yesterday" の "ye" に一致します。 |

### その他のアサーション

**メモ:** `?` の文字は数量詞としても使用されます。

| 文字 | 意味 |
| --- | --- |
| `x(?=y)` | **先読みアサーション:** "x" の後に "y" が続く場合のみ "x" に一致します。例えば、`/Jack(?=Sprat)/` は "Jack" の後に "Sprat" が続く場合のみ一致します。`/Jack(?=Sprat|Frost)/` は "Jack" の後に "Sprat" または "Frost" が続く場合のみ一致します。しかし、 "Sprat" も "Frost" も一致した結果には含まれません。 |
| `x(?!y)` | **否定先読みアサーション:** "x" の後に "y" が続いていない場合のみ "x" に一致します。例えば、 `/\d+(?!\.)/` は数字の後に小数点が続かない場合のみ一致します。`/\d+(?!\.)/.exec('3.141')`は "141" には一致しますが、 "3" には一致しません。 |
| `(?<=y)x` | **後読みアサーション:** "x" の前に "y" がある場合のみ "x" に一致します。例えば、`/(?<=Jack)Sprat/` は、 "Jack" が先行する場合のみ、 "Sprat" に一致します。 `/(?<=Jack|Tom)Sprat/` は、 "Jack" か "Tom" が先行する場合のみ、 "Sprat" に一致します。しかし、 "Jack" も "Tom" も一致した結果には含まれません。 |
| `(?<!y)x` | **否定後読みアサーション:** "x" の前に "y" がない場合のみ "x" に一致します。例えば、 `/(?<!-)\d+/` は、数字の前にマイナス記号がない場合のみ、数字に一致します。 `/(?<!-)\d+/.exec('3')` は "3" に一致します。 `/(?<!-)\d+/.exec('-3')` では数字の前にマイナス記号があるため、一致するものは見つかりません。 |

グループと後方参照
---------

グループと後方参照は、式の文字のグループを示します。

| 文字 | 意味 |
| --- | --- |
| `(*x*)` | **キャプチャグループ:** `*x*` に一致し、一致した内容を記憶します。例えば `/(foo)/` は "foo bar" の "foo" に一致し、記憶します。
正規表現は複数のキャプチャグループを持つことができます。結果、一般的にキャプチャグループ内の左括弧と同じ順にある、配列の要素のキャプチャグループに一致しています。たいていの場合、これはキャプチャグループ自身の順番です。これはキャプチャグループがネストしている場合に重要です。一致は結果の要素の添字 (`[1], …, [n]`) や、あらかじめ定義されている `RegExp` オブジェクトのプロパティ (`$1, …, $9`) を使ってアクセスできます。
キャプチャグループはパフォーマンス上の損失があります。一致した部分文字列を使わない場合はキャプチャしない括弧（後述）を使ったほうがいいでしょう。

`String.prototype.match()` は、`/.../g` フラグが設定されている場合、グループを返しません。しかし、
 `String.prototype.matchAll()` を使用して、すべての一致したものを取得することができます。
  |
| `(?<Name>x)` | **名前付きキャプチャグループ:** "x" に一致し、`<Name>` で指定された名前に従い、返される一致の `groups` プロパティに記憶されます。山括弧 ('`<`' と '`>`') にはグループ名が必須です。
例えば、電話番号からアメリカのエリアコードを取り出す際、 `/\((?<area>\d\d\d)\)/` を使うことができます。 結果の番号は `matches.groups.area` に表示されます。 |
| `(?:*x*)` | **非キャプチャグループ:** "x" に一致しますが、一致した内容は記憶しません。一致した部分文字列は、結果の配列の要素 (`[1], …, [n]`) や、あらかじめ定義されている `RegExp` オブジェクトのプロパティ (`$1, …, $9`) から呼び出すことはできません。
  |
| `\*n*` |
 "n" に正の整数が入ります。正規表現内において n 番目の括弧の部分に一致した最新の部分文字列への後方参照となります（括弧の数は左からカウントします）。例えば
 `/apple(,)\sorange\1/` は "apple, orange, cherry, peach" の
 "apple, orange," に一致します。
  |
| \k<Name> | `<Name>` で指定された**名前付きキャプチャグループ**に一致する最後の部分文字列の後方参照です。
例えば、 `/(?<title>\w+), yes \k<title>/` は、 "Do you copy? Sir, yes Sir!" の中の "Sir, yes Sir" に一致します。

**メモ:** `\k` は、ここでは、名前付きキャプチャグループの後方参照を開始することを示すために使用されています。
 |

数量詞
---

数量詞は、一致する文字や表現の数を示します。

**メモ:** 以下の表の中で、*アイテム*は単一の文字だけでなく、文字クラス、Unicode プロパティエスケープ、グループと後方参照を示すこともあります。

| 文字 | 意味 |
| --- | --- |
| `*x**` |
 直前のアイテム "x" の 0 回以上の繰り返しに一致します。例えば
 `/bo*/` は "A ghost booooed" の "boooo" や "A bird warbled"
 の "b" に一致しますが、 "A goat grunted" には一致しません。
  |
| `*x*+` |
 直前のアイテム "x" の 1 回以上の繰り返しに一致します。`{1,}`
 と同等です。例えば `/a+/` は "candy" の "a" や
 "caaaaaaandy" のすべての "a" に一致します。
  |
| `*x*?` |
 直前のアイテム "x" の 0 回か 1 回の出現に一致します。例えば
 `/e?le?/` は "angel" の "el" や "angle" の "le"
 に一致します。

`*`、`+`、`?`、`{}` といった数量詞の直後に使用した場合、既定とは逆に、その数量詞を非貪欲（出現回数が最小のものに一致）とします。既定は貪欲（出現回数が最大のものに一致）です。 |
| `*x*{*n*}` | "n" には正の整数が入ります。直前のアイテム "x" がちょうど "n" 回出現するものに一致します。例えば `/a{2}/` は "candy" の "a" には一致しませんが、"caandy" のすべての "a"、"caaandy" の最初の 2 つの "a" に一致します。 |
| `*x*{*n*,}` |
 "n" には正の整数が入ります。直前のアイテム "x" の少なくとも "n"
 回の出現に一致します。例えば、`/a{2,}/` は "candy" の "a"
 には一致しませんが、"caandy" や "caaaaaaandy" の "a"
 のすべてに一致します。
  |
| `*x*{*n*,*m*}` |
 "n" には 0 と正の整数が、 "m" には "n"
 より大きい正の整数が入ります。直前のアイテム "x" が少なくとも "n"
 回、多くても "m" 回出現するものに一致します。例えば
 `/a{1,3}/` は "cndy" では一致せず、"candy" の 'a'、"caandy"
 の 最初の 2 個の "a"、"caaaaaaandy" の最初の 3 個の "a"
 に一致します。"caaaaaaandy" では元の文字列に "a" が 4
 個以上ありますが、一致するのは "aaa" であることに注意してください。
  |
| `*x**?``*x*+?``*x*??``*x*{n}?``*x*{n,}?``*x*{n,m}?` | 既定では `*` や `+` といった数量詞は貪欲です。つまり、できる限り多くの文字列と一致しようとします。数量詞の後に `?` の文字を指定すると、数量詞が「非貪欲」になります。つまり、一致が見つかるとすぐに停止します。例えば、"some <foo> <bar> new </bar> </foo> thing" といった文字列が与えられた場合は、* `/<.*>/` は "<foo> <bar> new </bar> </foo>" に一致します。
* `/<.*?>/` は "<foo>" に一致します。
 |

Unicode プロパティエスケープ
------------------

Unicode プロパティエスケープでは、 Unicode プロパティに基づいた文字の照合を行うことができます。

```js
// バイナリー値でないもの
/\p{UnicodePropertyValue}/
/\p{UnicodePropertyName=UnicodePropertyValue}/

// バイナリー値と非バイナリー値
/\p{UnicodeBinaryPropertyName}/

// 否定: \P は \p の否定
/\P{UnicodePropertyValue}/
/\P{UnicodeBinaryPropertyName}/
```

`UnicodeBinaryPropertyName`

バイナリープロパティの名前。例えば、 `ASCII`, `Alpha`, `Math`, `Diacritic`, `Emoji`, `Hex_Digit`, `Math`, `White_space`, など。詳しくは Unicode Data PropList.txt を参照してください。

`UnicodePropertyName`

非バイナリープロパティの名前です。

* General\_Category (`gc`)
* Script (`sc`)
* Script\_Extensions (`scx`)

PropertyValueAliases.txt も参照してください。

`UnicodePropertyValue`

下記の「値」の節に掲載されているトークンの 1 つです。多くの値には、別名や短縮形があります（例えば `General_Category` プロパティの値 `Decimal_Number` は `Nd`, `digit`, `Decimal_Number` と書くことができます）。ほとんどの値では、 `UnicodePropertyName` の部分と等号を省略することができます。 `UnicodePropertyName` を指定した場合、その値は指定されたプロパティの種類に対応するものでなければなりません。

**メモ:** 利用できるプロパティと値は膨大であるため、ここでは網羅的に記述することはせず、様々な例を提供することにします。


グループと後方参照 - JavaScript

グループと後方参照
=========

グループは複数のパターンを全体としてグループ化し、グループをキャプチャすることで、正規表現パターンを使用して文字列と一致する場合に、追加の副一致情報を提供します。後方参照は、同じ正規表現で以前に捕捉したグループを参照します。

試してみましょう
--------

種類
--

| 文字 | 意味 |
| --- | --- |
| `(*x*)` | **キャプチャグループ:** `*x*` に一致し、一致した内容を記憶します。例えば `/(foo)/` は "foo bar" の "foo" に一致し、記憶します。
正規表現は複数のキャプチャグループを持つことができます。結果、一般的にキャプチャグループ内の左括弧と同じ順にある、配列の要素のキャプチャグループに一致しています。たいていの場合、これはキャプチャグループ自身の順番です。これはキャプチャグループがネストしている場合に重要です。一致は結果の要素の添字 (`[1], …, [n]`) や、あらかじめ定義されている `RegExp` オブジェクトのプロパティ (`$1, …, $9`) を使ってアクセスできます。
キャプチャグループはパフォーマンス上の損失があります。一致した部分文字列を使わない場合はキャプチャしない括弧（後述）を使ったほうがいいでしょう。

`String.prototype.match()` は、`/.../g` フラグが設定されている場合、グループを返しません。しかし、
 `String.prototype.matchAll()` を使用して、すべての一致したものを取得することができます。
  |
| `(?<Name>x)` | **名前付きキャプチャグループ:** "x" に一致し、`<Name>` で指定された名前に従い、返される一致の `groups` プロパティに記憶されます。山括弧 ('`<`' と '`>`') にはグループ名が必須です。
例えば、電話番号からアメリカのエリアコードを取り出す際、 `/\((?<area>\d\d\d)\)/` を使うことができます。 結果の番号は `matches.groups.area` に表示されます。 |
| `(?:*x*)` | **非キャプチャグループ:** "x" に一致しますが、一致した内容は記憶しません。一致した部分文字列は、結果の配列の要素 (`[1], …, [n]`) や、あらかじめ定義されている `RegExp` オブジェクトのプロパティ (`$1, …, $9`) から呼び出すことはできません。
  |
| `\*n*` |
 "n" に正の整数が入ります。正規表現内において n 番目の括弧の部分に一致した最新の部分文字列への後方参照となります（括弧の数は左からカウントします）。例えば
 `/apple(,)\sorange\1/` は "apple, orange, cherry, peach" の
 "apple, orange," に一致します。
  |
| `\k<Name>` | `<Name>` で指定された**名前付きキャプチャグループ**に一致する最後の部分文字列の後方参照です。
例えば、 `/(?<title>\w+), yes \k<title>/` は、 "Do you copy? Sir, yes Sir!" の中の "Sir, yes Sir" に一致します。

**メモ:** `\k` は、ここでは、名前付きキャプチャグループの後方参照を開始することを示すために使用されています。
 |

例
-

### グループの使用

```js
const personList = `First\_Name: John, Last\_Name: Doe
First\_Name: Jane, Last\_Name: Smith`;

const regexpNames = /First\_Name: (\w+), Last\_Name: (\w+)/gm;
for (const match of personList.matchAll(regexpNames)) {
  console.log(`Hello ${match[1]} ${match[2]}`);
}
```

### 名前付きグループの使用

```js
const personList = `First\_Name: John, Last\_Name: Doe
First\_Name: Jane, Last\_Name: Smith`;

const regexpNames =
  /First\_Name: (?<firstname>\w+), Last\_Name: (?<lastname>\w+)/gm;
for (const match of personList.matchAll(regexpNames)) {
  console.log(`Hello ${match.groups.firstname} ${match.groups.lastname}`);
}
```

### グループと後方参照の使用

```js
const quote = `Single quote "'" and double quote '"'`;
const regexpQuotes = /(['"]).\*?\1/g;
for (const match of quote.matchAll(regexpQuotes)) {
  console.log(match[0]);
}
```

### グループと一致結果の添字の使用

`d` フラグが指定された場合、各キャプチャグループの添字を返します。これは、それぞれの一致したグループと元のテキストを関連付ける場合、例えば、コンパイラーの診断を提供する場合に特に有益です。

```js
const code = `function add(x, y) {
 return x + y;
}`;
const functionRegexp =
  /(function\s+)(?<name>[$\_\p{ID\_Start}][$\u200c\u200d\p{ID\_Continue}]\*)/du;
const match = functionRegexp.exec(code);
const lines = code.split("\n");
lines.splice(
  1,
  0,
  " ".repeat(match.indices[1][1] - match.indices[1][0]) +
    "^".repeat(match.indices.groups.name[1] - match.indices.groups.name[0]),
);
console.log(lines.join("\n"));
// function add(x, y) {
// ^^^
// return x + y;
// }
```

関連情報
----

* `RegExp` 名前付きキャプチャグループが `core-js` で利用できます。
* 正規表現ガイド
    + 文字クラス
    + アサーション
    + 数量詞
    + Unicode プロパティエスケープ
* `RegExp()` コンストラクター
* ECMAScript 仕様書の ClassRanges（英語）


厳格モード - JavaScript

厳格モード
=====

**メモ:** 既定の厳格でないモードを *Sloppy モード* と呼ぶのを目にすることがあるかもしれません。これは公式な用語ではありません、念のため注意してください。

JavaScript の厳格モード (Strict mode) は、 JavaScript の自由度を制限することに**オプトイン**することによって、暗黙のうちに Sloppy モードからオプトアウトする方法です。厳格モードは単なるサブセットではなく、通常のコードとは**意図的に**異なる意味を持っています。厳格モードに対応していないブラウザーは、厳格モードに対応しているブラウザーとは異なる動作をする可能性がありますので、厳格モードに関する側面に対応しているかどうかの機能テストを行わずに厳格モードを頼らないでください。厳格モードのコードと非厳格モードのコードは共存できますので、スクリプトを順次厳格モードにオプトインすることができます。

厳格モードでは、通常の JavaScript の意味にいくつかの変更を加えます。

1. JavaScript で暗黙に失敗する一部のものを、エラーが発生するように変更することで除去します。
2. JavaScript エンジンによる最適化処理を困難にする誤りを修正します。厳格モードのコードは、非厳格モードのコードより高速に実行できる可能性があります。
3. 将来の ECMAScript で定義される予定の構文の使用を禁止します。
厳格モードの呼び出し
----------

厳格モードは**スクリプト全体**または**個別の関数**に適用できます。中括弧 `{}` で括られるブロック構文には適用できません。そのような場所に適用しようとしても何も起きません。`eval` のコード、 `Function` のコード、イベントハンドラー属性、`setTimeout()` などの関数に渡す文字列は、関数の本体またはスクリプト全体であり、厳格モードを呼び出すと期待どおりに動作します。

### スクリプトでの厳格モード

スクリプト全体で厳格モードを呼び出すには、他のいかなる文よりも前に `"use strict";` (または `'use strict';`) という文を**そのまま**追加します。

```js
// スクリプト全体の厳格モード構文
"use strict";
const v = "こんにちは！厳格モードのスクリプト！";
```

関数における厳格モード
-----------

同様に、関数で厳格モードを呼び出すには、関数本体で他のいかなる文よりも前に `"use strict";` (または `'use strict';`) という文を**そのまま**追加します。

```js
function myStrictFunction() {
  // 関数レベルの厳格モード構文
  "use strict";
  function nested() {
    return "私もそうです！";
  }
  return `こんにちは！厳格モードの関数です！ ${nested()}`;
}
function myNotStrictFunction() {
  return "厳格モードではありません。";
}
```

`"use strict"` ディレクティブは、単純な引数を持つ関数の本体にのみ使用することができます。 `"use strict"` を残余、デフォルト、分割引数のある関数で使用すると、構文エラーとなります。

```js
function sum(a = 1, b = 2) {
  // SyntaxError: "use strict" not allowed in function with default parameter
  "use strict";
  return a + b;
}
```

### モジュールでの厳格モード

JavaScript モジュールは内容全体が自動的に厳格モードになり、それを開始するための宣言は必要ありません。

```js
function myStrictFunction() {
  // これはモジュールなので、既定で厳格モードです
}
export default myStrictFunction;
```

### クラスでの厳格モード

クラス本体のすべての部分は、クラス宣言でもクラス式でも、厳格モードのコードになります。

```js
class C1 {
  // ここにあるコードはすべて厳格モードで評価されます
  test() {
    delete Object.prototype;
  }
}
new C1().test(); // TypeError。 test() が厳格モードであるため

const C2 = class {
  // ここにあるコードはすべて厳格モードで評価されます
};

// このコードは厳格なモードでない可能性があります。
delete Object.prototype; // エラーは発生しない
```

厳格モードでの変更点
----------

厳格モードでは構文と実行時動作の両方に変更を加わります。変更点は以下のカテゴリーに分類されます。

* ミスからエラー (構文エラーまたは実行時エラー) への変換
* 与えられた名前から特定の変数を算出する方法の単純化
* `eval` および `arguments` の単純化
* 「安全な」 JavaScript を書くことの容易化
* 将来の ECMAScript の進化への事前対処
### ミスからエラーへの変換

厳格モードでは、従来は受け入れていた一部のミスをエラーに変更します。JavaScript は未熟な開発者にも易しいように設計され、またエラーとすべき操作の一部をエラーとして扱いません。これにより当面の問題を解決したことがありますが、後により大きな問題を引き起こしたこともあります。厳格モードではこれらのミスをエラーとして扱うことで、開発者は気づいて修正するようになります。

#### 未宣言の変数への代入

厳格モードでは、偶発的にグローバル変数を作成できないようにします。厳格モードでない場合は、代入文で変数名の綴りを間違えるとグローバルオブジェクトに新しいプロパティが作成され、そしてそれは動作し続けます。厳格モードでは、代入文で偶発的にグローバル変数を作成せずにエラーが発生します。

```js
"use strict";
let mistypeVariable;

// グローバル変数 mistypeVarible が存在しない場合、
// この行は "mistypeVariable" のスペルミス
// （"a" がない）と見なして ReferenceError を発生させます。
mistypeVarible = 17;
```

#### オブジェクトプロパティへの代入の失敗

厳格モードでは、代入文で暗黙的に失敗せずに例外が発生するようにします。プロパティへの代入が失敗する条件は3 つあります。

* 書き込み不可のデータプロパティへの代入
* アクセサーがゲッターのみであるプロパティへの代入
* 拡張不可のオブジェクトにおける新しいプロパティへの代入

例えば、`NaN` は書き込み不可のグローバル変数です。厳格モードでない場合は、 `NaN` に代入しても何も起きません。つまり、開発者は失敗したという通知を受けません。厳格モードでは `NaN` に代入すると例外が発生します。

```js
"use strict";

// 書き換え不可能なグローバルへの代入
undefined = 5; // TypeError
Infinity = 5; // TypeError

// 書き換え不可能なプロパティへの代入
const obj1 = {};
Object.defineProperty(obj1, "x", { value: 42, writable: false });
obj1.x = 9; // TypeError

// ゲッターのみのプロパティへの代入
const obj2 = {
  get x() {
    return 17;
  },
};
obj2.x = 5; // TypeError

// 拡張不可能なオブジェクトの新しいプロパティへの代入
const fixed = {};
Object.preventExtensions(fixed);
fixed.newProp = "ohai"; // TypeError
```

#### オブジェクトプロパティの削除の失敗

厳格モードでは、削除操作を構成不可、またはその他の理由で削除できないプロパティ（例えば、プロキシーの `deleteProperty` ハンドラーが `false` を返すことで妨害されるもの）に対して試みると、例外が発生します（以前は何も起きませんでした）。

```js
"use strict";
delete Object.prototype; // TypeError
delete [].length; // TypeError
```

厳格モードでは、素の名前を削除することも禁じられています。 `delete name` は厳格モードでは構文エラーになります。

```js
"use strict";

var x;
delete x; // syntax error
```

名前が設定可能なグローバルプロパティの場合、それを削除するには `globalThis` を前に付けてください。

```js
"use strict";

delete globalThis.x;
```

#### 引数名の重複

厳格モードでは、関数の引数名が一意であることが要求されます。厳格モードでない場合は、引数の名前が重複していると、同じ名前の前の引数が見えなくなります。こうした前の引数は `arguments` を通せば利用可能なので、完全にアクセスできないわけではありません。しかし、この隠蔽はほとんど意味がなく、おそらく望ましくないものです（例えば、タイプミスを隠してしまうかもしれません）。したがって、厳格モードでは引数名が重複すると構文エラーになります。

```js
function sum(a, a, c) {
  // 構文エラー
  "use strict";
  return a + a + c; // このコードを実行したら失敗する
}
```

#### 古い 8 進数リテラル

厳格モードでは、`0` を先頭とした 8 進数表記や 8 進数エスケープシーケンスを禁止します。厳格モード以外では、 `0644` のような `0` で始まる数値は、すべての桁が 8 より小さい場合、 8 進数 (`0644 === 420`) として解釈されます。初心者の開発者は、接頭辞に何の意味もないと信じて、配置用の器具として使用することがありますが、これは数字の意味を変えてしまいます。 8 進数の先頭ゼロの構文はほとんど有益なものではなく、間違って使用される可能性があるため、厳格モードでは構文エラーとなります。

```js
"use strict";
const sum =
  015 + // 構文エラー
  197 +
  142;
```

8 進数のリテラルを表記する標準の方法は、以下のように `0o` の接頭辞を付けることです。

```js
const sumWithOctal = 0o10 + 8;
console.log(sumWithOctal); // 16
```

8 進数の拡張 ASCII 文字コード番号で文字を表わすために、 `"%"` と等しい `"\45"` のような 8 進数のエスケープシーケンスが使用できます。厳格モードでは、これは構文エラーになります。より正式には、 `\` に続いて `0` 以外の数字を続けたり `\0` に数字を続けたりすることは許されていません。例えば `\9` や `\07` の形は許されません。

#### プリミティブ値へのプロパティの設定

厳格モードでは、プリミティブ値にプロパティを設定することが禁止されます。プリミティブのプロパティにアクセスすると、暗黙に観察できないラッパーオブジェクトが生成されるため、厳格モードでない場合はプロパティの設定が無視されます（何も起こりません）。厳格モードでは `TypeError` が発生します。

```js
"use strict";

false.true = ""; // TypeError
(14).sailing = "home"; // TypeError
"with".you = "far away"; // TypeError
```

#### プロパティ名の重複

厳格モードのコードでは、プロパティ名が重複すると `SyntaxError` と見なされていました。プロパティ名の計算値の導入により、実行時に重複する可能性が出てきたため、 ECMAScript 2015 ではその制限が撤廃されました。

```js
"use strict";
const o = { p: 1, p: 2 }; // ECMAScript 2015 以前では構文エラー
```

**メモ:** これまでエラーとされていたコードをエラーでなくすこと、常に後方互換性があるものと見なされます。これは、言語がエラーを発生させることに厳格であることの良い部分であり、将来の意味づけの変更のための余地を残しています。

### スコープ管理の単純化

厳格モードでは、コード中の変数名と特定の変数定義との対応づけ方法を単純化します。多くのコンパイラーの最適化は、変数 *X* をある場所に保管している、と表現できることに依存しています。これは JavaScript のコードを最大限に最適化するために重要です。 JavaScript ではこのようなコード内の名前と変数定義との基本的な対応づけを、実行時まで行うことができない場合があります。厳格モードではこのような事態が起こるケースを取り除くことで、コンパイラが厳格モードのコードをより最適化できるようにします。

#### with 文の削除

厳格モードでは `with` を禁止しています。`with` の問題点は、ブロック内にある名前を、渡されたオブジェクトのプロパティまたはブロックの周囲（あるいはグローバル）のスコープへ実行時に対応づけることです。これは事前に行うことができません。厳格モードでは `with` をエラーとすることで、 `with` 内にある名前の指す場所が実行時に不明になる可能性をなくします。

```js
"use strict";
const x = 17;
with (obj) {
  // 構文エラー
  // 厳格モードでなかったら、これは const x と
  // obj.x のどちらになるのでしょうか？
  // コードを実行してみないと一概には言えないので、
  // 名前を最適化することはできません。
  x;
}
```

`with` の置き換えとして、オブジェクトに短い名前の変数を割り当て、その変数を用いて対応するプロパティにアクセスするという代案があります。

#### 漏洩のない eval

厳格モードでは、 `eval` は周囲のスコープに新しい変数を作成しません。厳格モードでない場合、 `eval("var x;")` というコードは、変数 `x` を周囲の関数やグローバルスコープに作成します。これは、一般的に `eval` の呼び出しを含む関数において、引数やローカル変数を参照していないすべての名前は、実行時に特定の定義に対応付けなければならないことを意味します（その `eval` が新しい変数を導入して、外側の変数を隠してしまうかもしれないからです）。厳格モードでは `eval` で評価されているコードでのみ使用できる変数を作成するので、変数名が外部の変数や一部のローカル変数を指しているかにかかわらず `eval` は影響を与えません。

```js
var x = 17;
var evalX = eval("'use strict'; var x = 42; x;");
console.assert(x === 17);
console.assert(evalX === 42);
```

`eval()` に渡された文字列が厳格なモードで評価されるかどうかは、 `eval()` の起動方法（直接 eval か間接 eval か）に依存します。

#### ブロックスコープ付き関数宣言

JavaScript の言語仕様では、当初からブロック文の中に関数宣言を入れ子で記述することを認めていませんでした。しかし、あまりにも直感的なため、ほとんどのブラウザーが拡張文法として実装していました。そして残念ながら、実装の意味づけが分かれ、言語仕様としてすべての実装を整合をとることが不可能になりました。そのため、ブロックスコープ付き関数宣言は厳格モードでのみ明示的に指定され（かつては厳格モードでは禁止されていた）、一方で厳格モードでない場合の動作は、ブラウザーによってばらついたままになっています。

### eval および arguments の単純化

厳格モードでは `arguments` および `eval` の奇妙さを低減します。通常のコードではどちらも不思議な動作がかなりあります。 `eval` でバインドを追加や削除したり、バインドする値を変更したり、 `arguments` の添字つきプロパティが名前付き引数の別名になることです。厳格モードでは、 `eval` と `arguments` をキーワードとして扱うことに大きく舵を切りました。

#### eval や arguments にバインドしたり代入したりしないようにする

`eval` および `arguments` という名前に対して言語構文でのバインドや代入を不可にしています。以下のような試みはすべて構文エラーになります。

```js
"use strict";
eval = 17;
arguments++;
++eval;
const obj = { set p(arguments) {} };
let eval;
try {
} catch (arguments) {}
function x(eval) {}
function arguments() {}
const y = function eval() {};
const f = new Function("arguments", "'use strict'; return 17;");
```

#### 引数と arguments の添字を同期させない

厳格モードのコードは、 `arguments` オブジェクトの添字を各引数のバインドと同期させません。厳格モードでない場合、最初の引数が `arg` である関数では、 `arg` に値を設定すると `arguments[0]` の値も設定され、その逆も同様です（引数を指定しなかったり `arguments[0]` を削除したりした場合を除く）。厳格モードの関数の `arguments` オブジェクトは、その関数が呼び出されたときの元の引数を格納します。 `arguments[i]` は対応する名前付き引数の値を追跡しません。

```js
function f(a) {
  "use strict";
  a = 42;
  return [a, arguments[0]];
}
const pair = f(17);
console.assert(pair[0] === 42);
console.assert(pair[1] === 17);
```

### JavaScript の「安全化」

厳格モードにより「安全な」 JavaScript の記述がより簡単になります。現在、一部のウェブサイトではユーザーに対し、ウェブサイトの**他のユーザーが**実行することができる JavaScript を記述する方法を提供しています。ブラウザーの JavaScript はユーザーの個人情報にアクセスできるため、実行前に部分的に変換し、禁止された機能へのアクセスを検閲する必要があります。しかし、 JavaScript は柔軟性に富んでいるため、多くの実行時チェックを行わないと事実上不可能です。ある種の言語関数は、実行時チェックを行うことでかなりのパフォーマンスコストがかかるほど浸透しています。いくつかの厳格モードの調整と、ユーザが投稿した JavaScript が厳格モードのコードであることと、特定の方法で呼び出されることを要求することで、これらの実行時チェックの必要性を大幅に減らすことができます。

#### `this` の置き換えを行わない

厳格モードでは、 `this` として関数に渡された値は強制的にオブジェクトに変換（別名「ボックス化」）しません。厳格モードでない関数では、 `this` は常にオブジェクトです。 `this` がオブジェクト値で呼び出された場合は提供されたオブジェクト、 `this` がプリミティブ値で呼び出された場合は、ボックス化された `this` の値、 `undefined` や `null` で呼び出された場合はグローバルオブジェクト、のいずれかになります。（特定の `this` を指定するには `call`、`apply`、`bind` を使用してください。）自動的にボックス化が行われるとパフォーマンスが犠牲となるだけでなく、ブラウザーでグローバルオブジェクトを公開することは、「安全な」 JavaScript 環境が制限しなければならない機能にグローバルオブジェクトがアクセスするため、セキュリティハザードになります。したがって、厳格モードの関数では、指定された `this` はオブジェクトにボックス化されず、指定されなかった場合は `globalThis` ではなく `undefined` となります。

```js
"use strict";
function fun() {
  return this;
}
console.assert(fun() === undefined);
console.assert(fun.call(2) === 2);
console.assert(fun.apply(null) === null);
console.assert(fun.call(undefined) === undefined);
console.assert(fun.bind(true)() === true);
```

#### 積み重ねプロパティの削除

厳格モードでは、JavaScript のスタックを「渡り歩く」ことができなくなりました。多くの実装では、関数の上流での呼び出し側を検出することが可能な、いくつかの拡張機能を使用していました。関数 `fun` が呼び出されている途中にあるとき、`fun.caller` は直近の `fun` を呼び出した関数で、`fun.arguments` はその `fun` の呼び出しのための `arguments` です。どちらの拡張も「安全な」 JavaScript にとって問題があります。なぜなら、「安全な」コードが「特権的な」関数とその（安全でない可能性のある）引数にアクセスすることを許してしまうからです。 `fun` が厳格モードの場合、 `fun.caller` と `fun.arguments` はどちらも削除不可能なプロパティで、設定されたり取得されたりすると例外が発生します。

```js
function restricted() {
  "use strict";
  restricted.caller; // TypeError が発生
  restricted.arguments; // TypeError が発生
}
function privilegedInvoker() {
  return restricted();
}
privilegedInvoker();
```

同様に、 `arguments.callee` も対応しなくなりました。厳格モードでない場合、 `arguments.callee` は包含関数を参照します。この用途は弱いです。囲む関数に名前をつけてください。 さらに、 `arguments.callee` は関数のインライン化などの最適化の妨げになります。 `arguments.callee` にアクセスした場合、インライン化されていない関数への参照を提供することが可能でなければならないからです。厳格モードの関数用の `arguments.callee` は削除できないプロパティで、設定したり取得したりするとエラーとなります。

```js
"use strict";
const f = function () {
  return arguments.callee;
};
f(); // TypeError が発生
```

### JavaScript の将来計画

#### 予約語の追加

予約語とは、変数名として使用できない識別子のことです。厳格モードでは、そうでないモードよりもいくつかの名前を予約しています。その中には、すでに言語で使用されているものもあれば、将来の構文拡張を実装しやすくするために予約されているものもあります。

* `implements`
* `interface`
* `let`
* `package`
* `private`
* `protected`
* `public`
* `static`
* `yield`
厳格モードへの移行
---------

厳格モードは、徐々に移行できるように設計されています。各ファイルを個別に変更することも可能ですし、関数の粒度まで厳格モードに移行させることも可能です。

最初にソースコードの一部に `"use strict"` を追加し、その後、意味づけの違いに注意しながら、すべての実行エラーを修正することで、コードベースを厳格モードに移行することができます。

### 構文エラー

`'use strict';` を追加すると、以下の場合にはスクリプトの実行前に `SyntaxError` が発生します。

* 8 進数の構文 `const n = 023;`
* `with` 文
* `delete` の変数名への使用 `delete myVariable`
* `eval` や `arguments` を変数名や関数の引数名に使用
* 新しい予約語の使用（将来的な言語機能を見据えて): `implements`, `interface`, `let`, `package`, `private`, `protected`, `public`, `static`, `yield`
* 関数の 2 つの引数を同じ名前で定義 `function f(a, b, b) {}`
* オブジェクトリテラルで、同じプロパティ名を二重に宣言 `{a: 1, b: 3, a: 7}`。この制限は後に取り除かれました（バグ 1041128）。

これらのエラーは、明白な誤りや悪しき習慣を明らかにするものであり、良いものです。これらのエラーはコードが実行される前に発生するので、コードがランタイムによって解釈される限り、容易に発見することができます。

### 新しいランタイムエラー

JavaScript で使用される場合、これまでエラーとされるべき状況では 黙って失敗していました。厳格モードはそのような場合に発生します。もしコードベースにそのようなケースがあれば、何も壊れていないことを確認するためにテストが必要でしょう。このようなエラーは、関数の粒度レベルで確認することができます。

* 未宣言の変数に代入すると `ReferenceError` が発生します。これはグローバルオブジェクトのプロパティを設定するために使用されますが、期待される効果はほとんどありません。もし、実際にグローバルオブジェクトに値を集合させたいのであれば、明示的に `globalThis` にプロパティとして代入してください。
* オブジェクトのプロパティへの代入に失敗すると（例えば読み取り専用であるなど）、 `TypeError` が発生します。厳格モードでない場合、これは黙って失敗します。
* 削除不可能なプロパティを削除しようとすると `TypeError` が発生します。厳格モードでない場合、これは黙って失敗します。
* 関数が厳格モードである場合、 `arguments.callee`、`strictFunction.caller`、`strictFunction.arguments` にアクセスすると `TypeError` が発生します。もし、関数を再帰的に呼び出すために `arguments.callee` を使用している場合は、代わりに名前付き関数式を使用してください。
### 意味づけの違い

これらの違いは、非常に微妙な違いです。テストスイートがこのような微妙な形を捉えないということもあり得ます。これらの差異がコードの意味づけに影響しないことを確認するために、コードベースの慎重なレビューがおそらく必要でしょう。幸いなことに、この慎重なレビューは、関数の粒度を徐々に下げて行うことができます。

`this`

厳格モードでない場合、 `f()` wのような関数呼び出しを行うと、 `this` 値としてグローバルオブジェクトが渡されまていした。厳格モードでは、これが `undefined` になりました。 `call` や `apply` で関数が呼び出されたとき、値がプリミティブな値だった場合、 `this` はオブジェクトにボックス化されていました（`undefined` や `null` の場合はグローバルオブジェクトになります）。厳格モードでは、値は変換されたりや置き換えられたりすることなく、直接渡されます。

`arguments`

厳格モードでない場合、 `arguments` オブジェクトの値を変更すると、対応する名前付き引数が変更されます。このため、 JavaScript エンジンの最適化が複雑になり、コードが読みにくく、理解しにくくなっていました。厳格モードでは、 `arguments` オブジェクトは名前付き引数と同じ値で作成・初期化されますが、 `arguments` オブジェクトと名前付き引数のどちらを変更しても、お互いに反映されることはありません。

`eval`

厳格モードのコードでは、 `eval` は呼び出されたスコープに新しい変数を作成することはありません。もちろん厳密モードでは、文字列は厳密モードの規則で評価されます。何も壊れないことを確認するために、徹底的なテストを行う必要があります。 eval が本当に必要でない場合には使用しない、というのも現実的な解決策かもしれません。

ブロックスコープ付き関数宣言

厳格モードでない場合、ブロック内の関数宣言はブロックの外側でも見ることができ、呼び出しも可能です。厳格モードでは、ブロック内の関数宣言はブロックの内部でしか見ることができません。

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification  |

関連情報
----

* JavaScript モジュールガイド
* 字句文法


クラス - JavaScript

クラス
===

Baseline Widely available
-------------------------

This feature is well established and works across many devices and browser versions. It’s been available across browsers since March 2017.

* Learn more
* See full compatibility
* Report feedback
クラスはオブジェクトを作成するためのテンプレートです。処理するためのコードでデータをカプセル化します。 JS のクラスはプロトタイプに基づいて構築されていますが、一部の構文や意味はクラスに固有です。

例や説明については、クラスの使用ガイドを参照してください。

解説
--

### クラスの定義

クラスは実際には「特別な関数」であり、関数式と関数宣言を定義することができるように、クラスもクラス式またはクラス宣言の 2 つの定義方法があります。

```js
// 宣言
class Rectangle {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}

// 式（クラスは無名だが、変数に代入される）
const Rectangle = class {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
};

// 式（自分の名前を持つクラス）
const Rectangle = class Rectangle2 {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
};
```

関数式と同様に、クラス式も無名であったり、割り当てる変数とは異なる名前を持ったりすることができます。しかし、関数宣言とは異なり、クラス宣言は `let` や `const` と同じ一時的なデッドゾーンの制約があり、巻き上げられていないかのように動作します。

### クラス本体

中括弧 `{}` 内にクラス本体を記述します。クラス本体には、メソッドやコンストラクターといったクラスメンバーを記述します。

クラス本体は `"use strict"` ディレクティブがなくても厳格モードで実行されます。

クラスの要素は 3 つの側面で特徴付けられます。

* 種類: ゲッター、セッター、メソッド、フィールド
* 場所: 静的またはインスタンス
* 可視性: パブリックまたはプライベート

これらを合計すると、使用可能な組み合わせは16通りになります。リファレンスをより論理的に分割し、コンテンツの重複を避けるため、異なる要素はそれぞれ別のページで詳しく紹介しています。

メソッド定義

パブリックインスタンスメソッド

ゲッター

パブリックインスタンスゲッター

セッター

パブリックインスタンスセッター

パブリッククラスフィールド

パブリックインスタンスフィールド

`static`

パブリック静的メソッド、ゲッター、セッター、フィールド

プライベートプロパティ

プライベートなものすべて

**メモ:** プライベート機能には、同じクラスで宣言するプロパティ名はすべて固有のものでなければならないという制約があります。他のすべてのパブリックプロパティにはこの制限はなく、同じ名前の複数のパブリックプロパティを持つことができ、最後のプロパティが他のプロパティを上書きします。これはオブジェクト初期化子での処理と同じです。

さらに、特別なクラス要素の構文として、 `constructor` と静的初期化ブロックの 2 つがあり、自分自身で参照します。

#### コンストラクター

`constructor` メソッドは、クラスで作成したオブジェクトを作成して初期化するための特別なメソッドです。 "constructor" という名前の特別なメソッドは、クラスに 1 つしか定義できません。クラスに複数の `constructor` メソッドが存在した場合、`SyntaxError` が発生します。

スーパークラスのコンストラクターはキーワード `super` を使用して呼び出すことができます。

コンストラクターの中でインスタンスプロパティを作成することができます。

```js
class Rectangle {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}
```

また、インスタンスプロパティの値がコンストラクターの引数に依存しない場合は、クラスフィールドとして定義することもできます。

#### 静的初期化ブロック

静的初期化ブロックは、初期化中に文の評価を含めることができ、プライベートスコープにアクセスしながら、静的プロパティの柔軟な初期化を行うことができます。

静的ブロックは複数宣言することができ、静的フィールドや静的メソッドの宣言と混在させることができます（静的項目はすべて宣言順に評価されます）。

#### メソッド

メソッドはクラスごとにプロトタイプに定義され、すべてのインスタンスで共有されます。メソッドには、プレーン関数、非同期関数、ジェネレーター関数、非同期ジェネレーター関数があります。詳しい情報は、メソッド定義を参照してください。

```js
class Rectangle {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
  // Getter
  get area() {
    return this.calcArea();
  }
  // Method
  calcArea() {
    return this.height \* this.width;
  }
  \*getSides() {
    yield this.height;
    yield this.width;
    yield this.height;
    yield this.width;
  }
}

const square = new Rectangle(10, 10);

console.log(square.area); // 100
console.log([...square.getSides()]); // [10, 10, 10, 10]
```

#### 静的メソッドとフィールド

`static` キーワードは、クラスの静的メソッドまたはフィールドを定義します。静的プロパティ（フィールドとメソッド）は、インスタンスごとに定義されるのではなく、クラス自体に定義されます。静的メソッドは、アプリケーションのユーティリティ関数を作成するために使用することが多く、一方、静的フィールドは、キャッシュや修正された構成など、インスタンス間で複製する必要のないデータに有益です。

```js
class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  static displayName = "Point";
  static distance(a, b) {
    const dx = a.x - b.x;
    const dy = a.y - b.y;

    return Math.hypot(dx, dy);
  }
}

const p1 = new Point(5, 5);
const p2 = new Point(10, 10);
p1.displayName; // undefined
p1.distance; // undefined
p2.displayName; // undefined
p2.distance; // undefined

console.log(Point.displayName); // "Point"
console.log(Point.distance(p1, p2)); // 7.0710678118654755
```

#### フィールド宣言

クラスのフィールド宣言構文では、コンストラクターの例は次のように書くことができます。

```js
class Rectangle {
  height = 0;
  width;
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}
```

クラスのフィールドはオブジェクトのプロパティに似ていて変数ではないので、宣言するために `const` などのキーワードは使用しません。 JavaScript では、プライベート機能は特別な識別子構文を使うので、 `public` や `private` のような修飾子キーワードも使うべきではありません。

上で見たように、フィールドは既定値付きで宣言することも、既定値なしで宣言することもできます。既定値のないフィールドは `undefined` が既定値となります。フィールドを前もって宣言することで、クラスの宣言がよりドキュメント化され、フィールドが常に存在するようになり、最適化しやすくします。

詳細はパブリッククラスフィールドを参照してください。

#### プライベートプロパティ

プライベートフィールドを使うと、宣言は下記のように宣言できます。

```js
class Rectangle {
  #height = 0;
  #width;
  constructor(height, width) {
    this.#height = height;
    this.#width = width;
  }
}
```

 クラスの外部からプライベートフィールドを参照するとエラーになります。これらのフィールドはクラス本体の内部でのみ読み書きできます。
 クラスの外から見えないことを定義することで、クラスのユーザーがバージョンごとに変わる内部構造に依存しないこと保証することができます。

プライベートフィールドは、フィールド宣言でのみ宣言できます。通常のプロパティのように、後から割り当てることで作成することはできません。

詳細情報については、プライベートプロパティを参照してください。

### 継承

`extends` キーワードは、クラスを別なクラス（クラスまたは関数）の子として作成するために、*クラス宣言*または*クラス式*の中で使います。

```js
class Animal {
  constructor(name) {
    this.name = name;
  }

  speak() {
    console.log(`${this.name}が鳴きます。`);
  }
}

class Dog extends Animal {
  constructor(name) {
    super(name); // スーパークラスのコンストラクターを呼び出し、 name 引数を渡す
  }

  speak() {
    console.log(`${this.name}が吠えます。`);
  }
}

const d = new Dog("ミッチー");
d.speak(); // ミッチーが吠えます。
```

サブクラスにコンストラクターが存在する場合は、 `this` を使用する前に、最初に `super()` を呼び出す必要があります。キーワード `super` を使用して、スーパークラスの対応するメソッドを呼び出すこともできます。

```js
class Cat {
  constructor(name) {
    this.name = name;
  }

  speak() {
    console.log(`${this.name}が鳴きます。`);
  }
}

class Lion extends Cat {
  speak() {
    super.speak();
    console.log(`${this.name}が吠えます。`);
  }
}

const l = new Lion("ファジー");
l.speak();
// ファジーが鳴きます。
// ファジーが吠えます。
```

### 評価の順序

`class` 宣言や `class` 式が評価されるとき、そのさまざまな構成要素は以下の順序で評価されます。

1. 最初に `extends` 節があれば、それが評価されます。これは有効なコンストラクター関数か `null` でなければならず、そうでなければ `TypeError` が発生します。
2. `constructor` メソッドが抽出され、 `constructor` が存在しない場合は既定の実装で置き換えられます。しかし、 `constructor` の定義は単なるメソッド定義であるため、この段階は観察することができません。
3. クラス要素のプロパティキーは宣言順に評価されます。プロパティキーが計算されたものである場合、計算された式が評価され、 `this` 値にはクラスを囲む `this` 値が設定されます（クラスそのものではありません）。プロパティ値はまだ評価されません。
4. メソッドとアクセサーは宣言順にインストールされます。インスタンスメソッドとアクセサーは現在のクラスの `prototype` プロパティにインストールされ、静的メソッドとアクセサーはクラス自体にインストールされます。プライベートインスタンスメソッドとアクセサーは、後でインスタンスに直接インストールするために保存されます。この段階は観察することができません。
5. これでクラスは `extends` で指定したプロトタイプと `constructor` で指定した実装で初期化されます。上記のすべての段階で、評価された式がクラスの名前にアクセスしようとすると、クラスがまだ初期化されていないため `ReferenceError` が発生します。
6. クラス要素の値は宣言順に評価されます。
    * インスタンスフィールド（パブリックまたはプライベート）ごとに、その初期化子式が保存されます。初期化子はインスタンス生成時、コンストラクタの開始時（基底クラスの場合）、または `super()` 呼び出しが返す直前（派生クラスの場合）に評価されます。
    * それぞれの静的フィールド（パブリックまたはプライベート）について、その初期化子は `this` をクラス自身に設定した状態で評価され、プロパティがクラス上に作成されます。
    * 静的初期化ブロックは `this` をクラス自身に設定した状態で評価されます。
7. これでクラスは完全に初期化され、コンストラクター関数として使用することができます。

インスタンスがどのように作成されるかは、 `constructor` を参照してください。

例
-

### インスタンスメソッドと静的メソッドのバインド

静的メソッドやインスタンスメソッドを `this` の値なしで呼び出した場合、例えばメソッドを変数に割り当ててから呼び出すと、メソッド内部では `this` の値が `undefined` になります。この動作は、 `"use strict"` ディレクティブが存在しない場合でも同じです。 `class` 本体の中のコードは常に厳格モードで実行されるからです。

```js
class Animal {
  speak() {
    return this;
  }
  static eat() {
    return this;
  }
}

const obj = new Animal();
obj.speak(); // the Animal object
const speak = obj.speak;
speak(); // undefined

Animal.eat(); // class Animal
const eat = Animal.eat;
eat(); // undefined
```

厳格モードでない従来の関数ベースの構文で上記を書き直すと、 `this` メソッド呼び出しは自動的に `globalThis` にバインドされます。厳格モードでは `this` の値は `undefined` のままです。

```js
function Animal() {}

Animal.prototype.speak = function () {
  return this;
};

Animal.eat = function () {
  return this;
};

const obj = new Animal();
const speak = obj.speak;
speak(); // global object (in non–strict mode)

const eat = Animal.eat;
eat(); // global object (in non-strict mode)
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-class-definitions |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* クラスの使用ガイド
* `class`
* `class` 式
* 関数
* ES6 In Depth: Classes (hacks.mozilla.org, 2015)


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

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

テンプレートリテラルはバッククォート (```) で区切られたリテラルで、*substitution*と呼ばれる埋め込み式が利用できます。

タグなし*テンプレートリテラルは文字列となるため、文字列の補間に便利です（エスケープされていない改行が許されるため、複数行の文字列も可能です）。
タグつき*テンプレートリテラルは、リテラルから任意のテキストセグメントの配列と、任意の置換の値を引数として関数（*タグ関数*）を呼び出します。これは、 DSL に便利です。

テンプレートリテラルは非公式に「*テンプレート文字列*」と呼ばれることもありますが、文字列リテラルではないので、文字列リテラルが使えるところならばどこでも使えるわけではありません。また、タグ付けされたテンプレートリテラルが文字列になるとは限りません。何を作成するかはタグ関数次第です（もし何か作成するのであれば）。

構文
--

```js
// タグなし。これらは文字列を生成します。
`string text`;

`string text line 1
 string text line 2`;

`string text ${expression} string text`;

// タグを付けると、関数 "example" を最初の引数にテンプレート、
// 後続の引数に置換値を指定して呼び出します。
example`string text ${expression} string text`;
```

解説
--

テンプレートリテラルは、ダブルクォートやシングルクォートの代わりにバッククォート文字 (```) （グレーブアクセント）で囲みます。

テンプレートリテラルにはプレースホルダーを含めることができます。プレースホルダーはドル記号と波括弧 (`${expression}`) で示されます。プレースホルダー内の式とバッククォート文字 (```) の間にあるテキストが関数に渡されます。

既定の関数は、単に各部を連結して 1 つの文字列とするだけです。テンプレートリテラルの前に式（ここでは `tag`）がある場合、これは**タグ付きテンプレート**と呼ばれます。この場合、タグ式（通常は関数）はテンプレートリテラルとともに呼び出され、出力する前にそれを操作することができます。

テンプレートリテラル内でバッククォート文字をエスケープするには、バッククォート文字の前にバックスラッシュ (`\`) を置きます。

```js
`\`` === "`"; // --> true
```

### 複数行の文字列

ソースの中に挿入された改行文字は、すべてテンプレートリテラルの一部になります。

通常の文字列を使う場合は、複数行の文字列を得るために次のような構文を使用する必要があります。

```js
console.log("string text line 1\n" + "string text line 2");
// "string text line 1
// string text line 2"
```

テンプレートリテラルを使用すれば、同じものを次のように書くことができます。

```js
console.log(`string text line 1
string text line 2`);
// "string text line 1
// string text line 2"
```

### 式の挿入

通常の文字列に式を埋め込むには、以下のような構文を使用していると思います。

```js
let a = 5;
let b = 10;
console.log("Fifteen is " + (a + b) + " and\nnot " + (2 \* a + b) + ".");
// "Fifteen is 15 and
// not 20."
```

テンプレートリテラルを使用すると、糖衣構文を使用して、このようにもっと読みやすく表記することができます。

```js
let a = 5;
let b = 10;
console.log(`Fifteen is ${a + b} and
not ${2 \* a + b}.`);
// "Fifteen is 15 and
// not 20."
```

### 入れ子のテンプレート

場合によっては、テンプレートを入れ子にすると、構成可能な文字列を得るのにもっとも簡単に（かつ、おそらくより読みやすく）なることがあります。バッククォートをつけたテンプレートでは、テンプレート内にあるプレイスホルダー `${ }` の内部でバッククォートを使用することができます。

例えば、条件式が `true` の場合、このテンプレートリテラルを `return` します。

ES5 の場合:

```js
let classes = "header";
classes += isLargeScreen()
  ? ""
  : item.isCollapsed
    ? " icon-expander"
    : " icon-collapser";
```

ES2015 で入れ子なしのテンプレートリテラルの場合:

```js
const classes = `header ${
 isLargeScreen() ? "" : item.isCollapsed ? "icon-expander" : "icon-collapser"
}`;
```

ES2015 で入れ子にしたテンプレートリテラルの場合:

```js
const classes = `header ${
 isLargeScreen() ? "" : `icon-${item.isCollapsed ? "expander" : "collapser"}`
}`;
```

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

**タグ付き**テンプレートは、テンプレートリテラルのより高度な形式です。

タグを使用すると、テンプレートリテラルを関数で解析できます。タグ関数の最初の引数には、文字列リテラルの配列を含みます。残りの引数は式に関連付けられます。

タグ関数は、これらの引数に対して何でも望み通りの操作を実行することができ、加工された文字列を返します。（または、以下の例の一つで示しているように、まったく異なるものを返すこともできます。）

タグに使用される関数の名前は、自由に指定できます。

```js
let person = "Mike";
let age = 28;

function myTag(strings, personExp, ageExp) {
  let str0 = strings[0]; // "That "
  let str1 = strings[1]; // " is a "
  let str2 = strings[2]; // "."

  let ageStr;
  if (ageExp > 99) {
    ageStr = "centenarian";
  } else {
    ageStr = "youngster";
  }

  // テンプレートリテラルを用いて組み立てた文字列を返すこともできます
  return `${str0}${personExp}${str1}${ageStr}${str2}`;
}

let output = myTag`That ${person} is a ${age}.`;

console.log(output);
// That Mike is a youngster.
```

タグ関数は文字列を返さなくても構いません。

```js
function template(strings, ...keys) {
  return function (...values) {
    let dict = values[values.length - 1] || {};
    let result = [strings[0]];
    keys.forEach(function (key, i) {
      let value = Number.isInteger(key) ? values[key] : dict[key];
      result.push(value, strings[i + 1]);
    });
    return result.join("");
  };
}

let t1Closure = template`${0}${1}${0}!`;
//let t1Closure = template(["","","","!"],0,1,0);
t1Closure("Y", "A"); // "YAY!"

let t2Closure = template`${0} ${"foo"}!`;
//let t2Closure = template([""," ","!"],0,"foo");
t2Closure("Hello", { foo: "World" }); // "Hello World!"

let t3Closure = template`I'm ${"name"}. I'm almost ${"age"} years old.`;
//let t3Closure = template(["I'm ", ". I'm almost ", " years old."], "name", "age");
t3Closure("foo", { name: "MDN", age: 30 }); //"I'm MDN. I'm almost 30 years old."
t3Closure({ name: "MDN", age: 30 }); //"I'm MDN. I'm almost 30 years old."
```

### 加工前の文字列

タグ関数に渡される第 1 引数では、特別な `raw` プロパティが利用できます。このプロパティを通して、エスケープシーケンスを処理する前の、入力された通りの加工前の文字列を参照することができます。

```js
function tag(strings) {
  console.log(strings.raw[0]);
}

tag`string text line 1 \n string text line 2`;
// logs "string text line 1 \n string text line 2" ,
// including the two characters '\' and 'n'
```

加えて、 `String.raw()` メソッドがあり、既定のテンプレート関数のように文字列を連結した形で加工前の文字列を生成することができます。

```js
let str = String.raw`Hi\n${2 + 3}!`;
// "Hi\\n5!"

str.length;
// 6

Array.from(str).join(",");
// "H,i,\\,n,5,!"
```

### タグ付きテンプレートとエスケープシーケンス

#### ES2016 での動作

ECMAScript 2016 時点では、タグ付きテンプレートの以下のエスケープシーケンスには、次のようなルールが適用されます。

* Unicode のエスケープシーケンスは "`\u`" で始まること。例: `\u00A9`
* Unicode のコードポイントのエスケープは "`\u{}`" で示すこと。例: `\u{2F804}`
* 16 進数のエスケープは "`\x`" で始まること。例: `\xA9`
* 8 進数のリテラルのエスケープは "`\0o`" で始まり、その後数字が続くこと。例: `\0o251`

このルールのもとでは、下に示す例のようなタグ付きテンプレートが問題となります。なぜなら、 ECMAScript の文法に従ってこのテキストを解釈しようとすると、パーサーは Unicode の有効のエスケープシーケンスを探そうとするも、不正な構文が検出されてしまうからです。

```js
latex`\unicode`;
// 古い ECMAScript バージョン (ES2016 以前) では、以下のような例外が投げられる
// SyntaxError: malformed Unicode character escape sequence
```

#### ES2018 revision での不正なエスケープシーケンス

タグ付きテンプレートでは、他のエスケープシーケンスが一般的な言語 (DSL、LaTeX など) の埋め込みも許容する必要があります。 ECMAScript のプロポーザル Template Literal Revision (Stage 4, to be integrated in the ECMAScript 2018 standard) では、タグ付きテンプレートから、ECMAScript のエスケープシーケンスについての構文的な制約が除外されています。

しかし、埋め込んで「加工された」結果の中においても、不正なエスケープシーケンスがあれば、それを提示する必要があります。こうした不正なエスケープシーケンスは、「加工された」の配列の中では、`undefined` の要素として表示されます。

```js
function latex(str) {
  return { cooked: str[0], raw: str.raw[0] };
}

latex`\unicode`;

// { cooked: undefined, raw: "\\unicode" }
```

このエスケープシーケンスの制約は、**タグ付き**テンプレートのみが除外となります。**タグ付きでない**テンプレートリテラルの場合は、除外対象ではありません:

```js
let bad = `bad escape sequence: \unicode`;
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-template-literals |

ブラウザーの互換性
---------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

関連情報
----

* `String`
* `String.raw()`
* 字句文法
* Template-like strings in ES3 compatible syntax
* "ES6 in Depth: Template strings" on hacks.mozilla.org