var - JavaScript

var
===

**`var`** 文は関数スコープまたはグローバルスコープの変数を宣言し、任意でそれをある値に初期化します。

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

構文
--

```js
var name1;
var name1 = value1;
var name1 = value1, name2 = value2;
var name1, name2 = value2;
var name1 = value1, name2, /\* …, \*/ nameN = valueN;
```

`nameN`

変数名です。正規の識別子です。

`valueN` 省略可

その変数の初期値です。有効な式なら何でも取ることができます。既定値は `undefined` です。

あるいは、分割代入を使用して変数を宣言することもできます。

```js
var { bar } = foo; // where foo = { bar:10, baz:12 };
/\* これは、値が 10 の 'bar' という名前の変数を作成します。 \*/
```

解説
--

`var` 宣言は、現れる場所に関係なく、コードを実行する前に処理されます。これは巻き上げと呼ばれており、後述します。

`var` で宣言された変数のスコープは、その現在の*実行コンテキストとそのクロージャ*であり、その中で宣言された関数、あるいは関数の外で宣言された変数の場合はグローバルになります。`var` を使用して変数を重複して宣言しても、厳格モードであってもエラーは発生せず、別の代入が実行されない限り、変数の値は失われません。

```js
function foo() {
  var x = 1;
  function bar() {
    var y = 2;
    console.log(x); // 1 (function `bar` closes over `x`)
    console.log(y); // 2 (`y` is in scope)
  }
  bar();
  console.log(x); // 1 (`x` is in scope)
  console.log(y); // ReferenceError, `y` は `bar` のスコープ
}

foo();
```

`var` を使用して宣言された変数は、コードが実行されるよりも前に生成され、これは巻き上げと呼ばれています。これらの変数の初期値は `undefined` です。

```js
console.log(x); // undefined（注: ReferenceError ではない）
console.log("still going..."); // still going...
var x = 1;
console.log(x); // 1
console.log("still going..."); // still going...
```

グローバルコンテキストにおいては、`var` を使用して宣言された変数は、グローバルオブジェクトの構成不可能なプロパティとして追加されます。これは、プロパティ記述子を変更することができず、`delete` を使用して削除することができないことを意味します。対応する名前はグローバル環境レコード （グローバル字句環境の一部の形）内部の `[[VarNames]]` スロットにも追加されます。`[[VarNames]]` 内の名前のリストにより、ランタイムがグローバル変数とグローバルオブジェクトの直接のプロパティを区別することができます。

グローバル変数用のグローバルオブジェクトに作成されたプロパティは、グローバルオブジェクトの直接のプロパティではなく、識別子を変数として扱うことになるため、構成不可に設定されています。 JavaScript には自動メモリー管理機能があるため、グローバル変数に `delete` 演算子を使えるようにしても意味がありません。

```js
"use strict";
var x = 1;
Object.hasOwn(globalThis, "x"); // true
delete globalThis.x; // 厳格モードでは TypeError。それ以外の場合は暗黙に失敗します。
delete x; // 厳格モードでは SyntaxError。それ以外の場合は暗黙に失敗します。
```

なお、 NodeJS の CommonJS モジュールとネイティブの ECMAScript モジュールのどちらも、最上位の変数宣言はそのモジュールのスコープとなるので、グローバルオブジェクトのプロパティとしては追加されません。

### 無修飾の識別子の代入

グローバルオブジェクトは、スコープチェインの最上位に位置します。名前を値に解決しようとすると、スコープチェインが検索されます。これは、グローバルオブジェクトのプロパティをすべてのスコープから、 `globalThis.` や `window.` や `global.` などの修飾名なしで便利に見ることができることを意味します。

グローバルオブジェクトは `String` プロパティを持っているので（`Object.hasOwn(globalThis, 'String')`）、以下のコードを使用することができます。

```js
function foo() {
  String("s"); // `String` 関数が暗黙に見える
}
```

つまり、グローバルオブジェクトは最終的に修飾されていない識別子を検索することになります。`globalThis.String` と記述する必要はなく、修飾されていない `String` と記述すればよいのです。厳格モードでない場合は、スコープチェインで宣言されている同名の変数がない場合は、グローバルオブジェクト上にその名前のプロパティを作成しようとしていると仮定して、非修飾識別子に代入することになります。

```js
foo = "f"; // 厳格モードでない場合は、`foo` という名前のプロパティを作成しようとしていると見なす
Object.hasOwn(globalThis, "foo"); // true
```

厳格モードでは、修飾されていない識別子への代入しようとすると、`ReferenceError` が発生し、グローバルオブジェクトに意図せずプロパティが生成されることを防ぎます。

上記の意味合いは、一般的に誤解されていますが、JavaScript には暗黙の変数や宣言されていない変数をは存在せず、単にそのように見える構文を持っているだけだということに注意してください。

### var の巻き上げ

`var` の宣言はコードを実行する前に処理されますので、変数はコード内のどこで宣言しても、コードの先頭で宣言したものと等価になります。また、変数を宣言する前に変数を使用することもできます。この動作は、変数の宣言が関数やグローバルのコードの先頭に移動したように見えるため、巻き上げと呼ばれます。

```js
bla = 2;
var bla;
```

次のように見なされます。

```js
var bla;
bla = 2;
```

このため、変数は常にスコープ（グローバルのコードまたは関数のコード）の先頭で宣言することをお勧めします。そうすればどの変数が関数スコープ（ローカル）であるか、あるいはスコープチェインによって解決されたものかが明確になります。

ここで重要なのは、変数の定義のみが巻き上げられ、初期化は巻き上げられないことです。初期化は代入文に到達したときにのみ行われます。それまでは変数は `undefined` （ただし宣言された状態）のままになります。

```js
function do\_something() {
  console.log(bar); // undefined
  var bar = 111;
  console.log(bar); // 111
}
```

これは、暗黙的には次のように解釈されます。

```js
function do\_something() {
  var bar;
  console.log(bar); // undefined
  bar = 111;
  console.log(bar); // 111
}
```

例
-

### 2 つの変数を宣言して初期化する

```js
var a = 0,
  b = 0;
```

### 2 つの変数に 1 つの文字列を代入する

```js
var a = "A";
var b = a;
```

これは、以下と等価です。

```js
var a, b = a = 'A';
```

順番に注意してください。

```js
var x = y,
  y = "A";
console.log(x + y); // undefinedA
```

ここではコードを実行する前に `x` と `y` が宣言され、そのあとに代入を行います。"`x = y`" を実行したとき、`y` が存在しますので `ReferenceError` は発生せず、値は `undefined` になります。よって、`x` に undefined 値が代入されます。そして、`y` に値 'A' が代入されます。その結果、1 行目の後は `x === undefined && y === 'A'` となり、最終結果に至ります。

### 複数の変数を初期化する

```js
var x = 0;
function f() {
  var x = y = 1; // x はローカルで宣言されます。y は違います!
}
f();

console.log(x, y); // 0 1

// 厳格モードではない場合:
// x は想定どおり、グローバル側の変数です。
// しかし、y は関数の外部に漏れ出ています!
```

上記と同じ例を厳格モードで実行した場合は、次のようになります。

```js
"use strict";

var x = 0;
function f() {
  var x = y = 1; // 厳格モードでは ReferenceError が発生します。
}
f();

console.log(x, y);
```

### 暗黙のグローバル変数と関数スコープの外部

暗黙的にグローバルに現れた変数は、関数スコープの外部で参照することができます。

```js
var x = 0; // x はファイルスコープで宣言して、値 0 を代入

console.log(typeof z); // z はまだ存在していないため、 "undefined" になる

function a() {
  // a を呼び出すと、
  var y = 2; // y を関数 a のスコープで宣言して、値 2 を代入

  console.log(x, y); // 0 2

  function b() {
    x = 3; // ファイルスコープにある x に 3 を代入
    y = 4; // 外側の y に 4 を代入
    z = 5; // 新たなグローバル変数 z を生成して、値 5 を代入
    // （厳格モードでは ReferenceError が発生）
  }

  b(); // グローバル変数として z を生成
  console.log(x, y, z); // 3 4 5
}

a(); // b も呼び出す
console.log(x, z); // 3 5
console.log(typeof y); // y は関数 a のローカル変数であるため "undefined" になる
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-variable-statement |

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

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

関連情報
----

* `let`
* `const`


空文 - JavaScript

空文
==

**空文** は、JavaScript 構文で文が想定されているときに、文を用意しないために使います。

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

構文
--

```js
;
```

解説
--

空文はセミコロン (`;`) で、JavaScript の構文上で文を必要とするときでも文を実行しないことを示します。

逆のふるまいとして、 JavaScript が単一文のみ許可しているのに複数の文にしたい場合には、ブロック文を使ってください。ブロック文は、いくつかの文を単一文に結合します。

例
-

### 空のループ本体

空文は、ループ文で使われることがあります。ループ本体が空である以下の例をご覧ください。

```js
const arr = [1, 2, 3];

// 配列の値をすべて 0 にする
for (let i = 0; i < arr.length; arr[i++] = 0) /\* 空文 \*/ ;

console.log(arr);
// [0, 0, 0]
```

### 意図的でない使用

空文を*意図的*に使っていることをコメントするとよいでしょう。通常のセミコロンと区別するのが難しいからです。

次の例は、おそらく意図的でない使用例です。

```js
if (condition); // 注意: この "if" は何の意味もない!
killTheUniverse(); // この関数が常に実行される!!!
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-empty-statement |

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

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

関連情報
----

* ブロック文


for await...of - JavaScript

for await...of
==============

**`for await...of`** 文は、非同期反復可能オブジェクトを、同期反復可能オブジェクトと同様に反復処理するループを作成します。この文は. `await`　が使用できるコンテキスト、例えば非同期関数の本体やモジュール内などでのみ使用できます。

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

構文
--

```js
for await (variable of iterable)
  statement
```

`variable`

一連の反復処理の各回において、値を受け取ります。`const`、`let`、`var` の何れかの宣言や、代入文のターゲットとなるもの（前もって宣言された変数やオブジェクトプロパティ）を指定することができます。

`iterable`

非同期反復可能オブジェクトまたは同期反復可能オブジェクト。このループが処理する一連の値の元となるものです。

`statement`

反復処理のたびに実行される文です。`variable` を参照することができます。ブロック文を使用して、複数の文を実行することができます。

解説
--

`for await...of` ループが反復可能オブジェクトを反復処理する場合、最初に反復可能オブジェクトの `[@@asyncIterator]()` メソッドを取得してそれを呼び出すと、非同期イテレーターが返されます。`@asyncIterator` メソッドが存在しない場合は、次に `[@@iterator]()` メソッドを探し、同期イテレーターを返します。次に、 `next()`、`return()`、`throw()` メソッドから返されるすべてのオブジェクトを解決済みまたは拒否済みのプロミスにラップし、`value` プロパティがプロミスであれば解決済みにすることで、返された同期イテレーターを非同期イテレーターにラップします。ループは、最終的な非同期イテレーターの `next()` メソッドを繰り返し呼び出して、返されるプロミスを待ち、`variable` に代入される一連の値を生成します。

`for await...of` ループが早期に終了した場合（例えば、`break` 文に遭遇したり、エラーが throw された場合）、クリーンアップを実行するためにイテレーターの `return()` メソッドが呼び出されます。返されたプロミスは、ループが終了する前に待機されます。

`for await...of` は全般的に `for...of` ループと同様に機能し、構文や意味も共通しています。いくらか違いがあります。

* `for await...of` は同期または非同期の反復可能オブジェクトで動作しますが、 `for...of` は同期反復可能オブジェクトでのみ動作します。
* `for await...of` は `await` が使えるコンテキストでのみ使用できます。これは非同期関数の本体やモジュール内などです。反復可能オブジェクトが同期の場合でも、ループは反復処理のたびに返値を待つことになり、プロミスのラップ解除を繰り返すため実行速度が遅くなります。
* `iterable` がプロミスを生成する同期反復可能オブジェクトである場合、`for await...of` は解決された値のシーケンスを生成するのに対し `for...of` はプロミスのシーケンスを生成します。（ただし、エラー処理と後始末には注意が必要です。同期の反復可能オブジェクトおよびジェネレーターの反復処理を参照してください。）
* `for await...of` では、`variable` に識別子 `async` を取ることができます（例えば `for await (async of foo)`）。`for...of` では禁止されています。
例
-

### 非同期の反復可能オブジェクトでの繰り返し処理

非同期反復可能プロトコルを明示的に実装しているオブジェクトを反復処理することができます。

```js
const LIMIT = 3;

const asyncIterable = {
  [Symbol.asyncIterator]() {
    let i = 0;
    return {
      next() {
        const done = i === LIMIT;
        const value = done ? undefined : i++;
        return Promise.resolve({ value, done });
      },
      return() {
        // This will be reached if the consumer called 'break' or 'return' early in the loop.
        return { done: true };
      },
    };
  },
};

(async () => {
  for await (const num of asyncIterable) {
    console.log(num);
  }
})();
// 0
// 1
// 2
```

### 非同期のジェネレータの反復処理

非同期の反復可能プロトコルを実装している非同期ジェネレーターであれば、 `for await...of` を使用して繰り返し処理を行うことができます。

```js
async function\* asyncGenerator() {
  let i = 0;
  while (i < 3) {
    yield i++;
  }
}

(async () => {
  for await (const num of asyncGenerator()) {
    console.log(num);
  }
})();
// 0
// 1
// 2
```

`for await...of` を使用して非同期ジェネレータを反復処理するより具体的な例として、API からのデータを反復処理することを考えてみましょう。

この例では、まずデータのストリームに対して非同期の反復可能オブジェクトを作成し、それを使用して API からのレスポンスの長さを計算します。

```js
async function\* streamAsyncIterable(stream) {
  const reader = stream.getReader();
  try {
    while (true) {
      const { done, value } = await reader.read();
      if (done) return;
      yield value;
    }
  } finally {
    reader.releaseLock();
  }
}

// URL からデータを取得し、非同期ジェネレータを使用してレスポンスの長さを計算します。
async function getResponseSize(url) {
  const response = await fetch(url);
  // レスポンスの長さをバイト単位で保持する
  let responseSize = 0;
  // for-await-of ループ。レスポンスの各部分を非同期に反復処理します。
  for await (const chunk of streamAsyncIterable(response.body)) {
    // レスポンスの全長に加算
    responseSize += chunk.length;
  }

  console.log(`Response Size: ${responseSize} bytes`); // "Response Size: 1071472"
  return responseSize;
}
getResponseSize("https://jsonplaceholder.typicode.com/photos");
```

### 同期の反復可能オブジェクトおよびジェネレーターの反復処理

`for await...of` ループは同期の反復可能オブジェクトやジェネレーターで使用することもできます。この場合、内部的にはループの制御変数に代入する前に、値が出力されるのを待ちます。

```js
function\* generator() {
  yield 0;
  yield 1;
  yield Promise.resolve(2);
  yield Promise.resolve(3);
  yield 4;
}

(async () => {
  for await (const num of generator()) {
    console.log(num);
  }
})();
// 0
// 1
// 2
// 3
// 4

// for-of ループとの比較:

for (const numOrPromise of generator()) {
  console.log(numOrPromise);
}
// 0
// 1
// Promise { 2 }
// Promise { 3 }
// 4
```

**メモ:** 同期のジェネレーターから拒否されたプロミスが生み出される場合があることに注意してください。このような場合、 `for await...of` は拒否されたプロミスを消費するので、ジェネレーター内の `finally` ブロックが呼び出されません。これは、確保したリソースを `try/finally` で解放する必要がある場合は望ましくない動作になる可能性があります。

```js
function\* generatorWithRejectedPromises() {
  try {
    yield 0;
    yield 1;
    yield Promise.resolve(2);
    yield Promise.reject(3);
    yield 4;
    throw 5;
  } finally {
    console.log("called finally");
  }
}

(async () => {
  try {
    for await (const num of generatorWithRejectedPromises()) {
      console.log(num);
    }
  } catch (e) {
    console.log("caught", e);
  }
})();
// 0
// 1
// 2
// caught 3

// compare with for-of loop:

try {
  for (const numOrPromise of generatorWithRejectedPromises()) {
    console.log(numOrPromise);
  }
} catch (e) {
  console.log("caught", e);
}
// 0
// 1
// Promise { 2 }
// Promise { <rejected> 3 }
// 4
// caught 5
// called finally
```

同期ジェネレーター関数の `finally` ブロックが常に呼び出されるようにするには、非同期のジェネレーター関数の場合は `for await...of` を、同期ジェネレーター関数の場合は `for...of` を使用し、ループの中で生成されたプロミスを明示的に待つようにしてください。

```js
(async () => {
  try {
    for (const numOrPromise of generatorWithRejectedPromises()) {
      console.log(await numOrPromise);
    }
  } catch (e) {
    console.log("caught", e);
  }
})();
// 0
// 1
// 2
// caught 3
// called finally
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-for-in-and-for-of-statements |

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

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

関連情報
----

* `Symbol.asyncIterator`
* `for...of`


continue - JavaScript

continue
========

**`continue`** 文は、現在のループまたはラベル付きループの現在反復処理中の文の実行を終了し、次の反復処理としてループの実行を続けます。

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

構文
--

```js
continue;
continue label;
```

`label` 省略可

その文のラベルに関連付けられた識別子。

解説
--

`break` 文と対照的に、 `continue` はループの実行を完全には終了しません。代わりに、

* `while` または `do...while` ループでは、条件式にジャンプします。
* `for` ループでは、更新式にジャンプします。
* `for...in`、`for...of`、`for await...of` ループでは、次の反復処理にジャンプします。

`continue` 文には任意でラベルを含めることができ、現在のループの代わりにラベル付きループ文の次の反復処理へジャンプすることができます。この場合、`continue` 文は、ラベル付き文の中にある必要があります。

`continue` 文は、その後にラベルがあるかどうかに関わらず、スクリプト、モジュール、関数の本体、静的初期化ブロックのそれぞれ最上位で使用することはできません。その関数やクラスがさらにループの中に含まれていた場合でもです。

例
-

### while における continue の使用

次の例では、 `while` ループで `i` の値が 3 であるときに実行される `continue` 文を持つものを示しています。よって、 `n` は 1、3、7、12 の値をとります。

```js
let i = 0;
let n = 0;

while (i < 5) {
  i++;

  if (i === 3) {
    continue;
  }

  n += i;
}
```

### ラベル付き continue の使用

次の例では、`checkIAndJ` とラベル付けされた文が、`checkJ` とラベル付けされた文を含んでいます。もし `continue` と遭遇したなら、プログラムは `checkJ` 文の先頭から継続します。`continue` と遭遇するたびに、`checkJ` の条件が false を返すまで、`checkJ` は再度反復処理します。false が返されたら、`checkIAndJ` 文の残りが完遂されます。

もし `continue` がラベル `checkIAndJ` を持っていたなら、プログラムは `checkIAndJ` 文の先頭から継続します。

```js
let i = 0;
let j = 8;

checkIAndJ: while (i < 4) {
  console.log(`i: ${i}`);
  i += 1;

  checkJ: while (j > 4) {
    console.log(`j: ${j}`);
    j -= 1;

    if (j % 2 === 0) continue checkJ;
    console.log(`${j} is odd.`);
  }
  console.log(`i = ${i}`);
  console.log(`j = ${j}`);
}
```

結果:
```

i: 0

// start checkj
j: 8
7 is odd.
j: 7
j: 6
5 is odd.
j: 5
// end checkj

i = 1
j = 4

i: 1
i = 2
j = 4

i: 2
i = 3
j = 4

i: 3
i = 4
j = 4
```

### 構文違反の continue 文

`continue` は関数の境界をまたがるループ内で使用することはできません。

```js
for (let i = 0; i < 10; i++) {
  (() => {
    continue; // SyntaxError: Illegal continue statement: no surrounding iteration statement
  })();
}
```

ラベルを参照する場合は、ラベル付きの文がその `continue` 文を含んでいなければなりません。

```js
label: for (let i = 0; i < 10; i++) {
  console.log(i);
}

for (let i = 0; i < 10; i++) {
  continue label; // SyntaxError: Undefined label 'label'
}
```

ラベル付きの文はループでなければなりません。

```js
label: {
  for (let i = 0; i < 10; i++) {
    continue label; // SyntaxError: Illegal continue statement: 'label' does not denote an iteration statement
  }
}
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-continue-statement |

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

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

関連情報
----

* `break`
* ラベル


for...of - JavaScript

for...of
========

**`for...of`** 文は、反復可能オブジェクトをソースとした一連の値を処理するループを実行します。反復可能オブジェクトには、
 たとえば組み込みの `Array`, `String`, `TypedArray`, `Map`, `Set`, `NodeList`（およびその他の DOM コレクション）、同様に `arguments` オブジェクトや、ジェネレーター関数から生成されるジェネレーター、ユーザー定義の反復可能オブジェクトなどがあります。

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

構文
--

```js
for (variable of iterable)
  statement
```

`variable`

反復処理の各回において、一連のデータから値を受け取ります。`const`, `let`, `var` の何れかで定義されたものか、代入のターゲットとなります（以前に宣言した変数や、オブジェクトプロパティなど）。

`iterable`

反復可能オブジェクトです。ループを実行する一連の値の元となるものです。

`statement`

反復処理のたびに実行される文です。`variable` を参照することができます。ブロック文を使用して、複数の文を実行することができます。

解説
--

`for...of` ループは、反復可能オブジェクトから取り出した値を 1 つずつ順次処理します。ループが値に対して行う各処理は反復処理と呼ばれ、ループは反復可能オブジェクトを反復処理すると言います。それぞれの反復処理では、現在のシーケンス値を参照する可能性のある文が実行されます。

`for...of` ループが反復可能オブジェクトを反復処理する場合、最初にその反復可能オブジェクトの `[@@iterator]()` メソッドが呼び出されます。これはイテレーターを返すので、その返されたイテレーターの `next()` メソッドを呼び出すことで、`variable` に代入される一連の値を生成することができます。

`for...of` ループは、イテレーターが完全に処理したときに終了します（イテレーターの `next()` メソッドは `done: true` を含むオブジェクトを返します）。また、通常の制御フローを変更するために制御フロー文を使用することもできます。`break` はループを抜けてループ本体の後の最初のステートメントに進み、`continue` は現在の反復処理の残りの文をスキップして次の反復処理に進みます。

`for...of` ループが早期に終了した場合（例えば、`break` 文に遭遇したり、エラーが発生した場合）、`return()` のメソッドが呼び出されクリーンアップ処理が行われます。

`for...of` の `variable` 部分は、`=` 演算子の前に来ることができるものなら何でも受け入れることができます。`const` を使用して、ループ本体の中で再代入されない変数を宣言することができます（反復処理間では変更できます。2 つの別個の変数として扱われるからです）。そうでない場合は、`let` を使用してください。

```js
const iterable = [10, 20, 30];

for (let value of iterable) {
  value += 1;
  console.log(value);
}
// 11
// 21
// 31
```

**メモ:** 反復処理ごとに新しい変数が作成されます。ループ本体内で変数を再代入しても、反復可能オブジェクト（この場合は配列）の元の値には影響しません。

分割代入や、`for (x.y of iterable)` などのオブジェクトプロパティを使用することもできます。

しかし、特別なルールにより、変数名として `async` を使用することは禁じられています。これは無効な構文です。

```js
let async;
for (async of [1, 2, 3]); // SyntaxError: The left-hand side of a for-of loop may not be 'async'.
```

これは、`for` ループである有効なコード `for (async of => {};)` との構文のあいまいさを避けるためです。

例
-

### Array に対する反復処理

```js
const iterable = [10, 20, 30];

for (const value of iterable) {
  console.log(value);
}
// 10
// 20
// 30
```

### 文字列に対する反復処理

文字列は Unicode コードポイントで反復処理します。

```js
const iterable = "boo";

for (const value of iterable) {
  console.log(value);
}
// "b"
// "o"
// "o"
```

### 型付き配列に対する反復処理

```js
const iterable = new Uint8Array([0x00, 0xff]);

for (const value of iterable) {
  console.log(value);
}
// 0
// 255
```

### Map に対する反復処理

```js
const iterable = new Map([
  ["a", 1],
  ["b", 2],
  ["c", 3],
]);

for (const entry of iterable) {
  console.log(entry);
}
// ['a', 1]
// ['b', 2]
// ['c', 3]

for (const [key, value] of iterable) {
  console.log(value);
}
// 1
// 2
// 3
```

### Set に対する反復処理

```js
const iterable = new Set([1, 1, 2, 2, 3, 3]);

for (const value of iterable) {
  console.log(value);
}
// 1
// 2
// 3
```

### arguments オブジェクトに対する反復処理

`arguments` オブジェクトで反復処理をすると、ある JavaScript 関数にすべての引数を渡すことができます。

```js
function foo() {
  for (const value of arguments) {
    console.log(value);
  }
}

foo(1, 2, 3);
// 1
// 2
// 3
```

### NodeList に対する反復処理

次の例では `read` クラスを、`<article>` 要素の直接の子孫である段落に対して追加します。DOM の `NodeList` コレクションを反復処理すること実現します。

```js
const articleParagraphs = document.querySelectorAll("article > p");
for (const paragraph of articleParagraphs) {
  paragraph.classList.add("read");
}
```

### ユーザー定義の反復可能オブジェクトに対する反復処理

独自のイテレーターを返す `@@iterator` メソッドで、オブジェクトを反復処理します。

```js
const iterable = {
  [Symbol.iterator]() {
    let i = 1;
    return {
      next() {
        if (i <= 3) {
          return { value: i++, done: false };
        }
        return { value: undefined, done: true };
      },
    };
  },
};

for (const value of iterable) {
  console.log(value);
}
// 1
// 2
// 3
```

オブジェクトを `@@iterator` ジェネレーターメソッドで反復処理します。

```js
const iterable = {
  \*[Symbol.iterator]() {
    yield 1;
    yield 2;
    yield 3;
  },
};

for (const value of iterable) {
  console.log(value);
}
// 1
// 2
// 3
```

反復可能なイテレーター（`this` を返す `[@@iterator]()` メソッドを持つイテレーター）は、`for...of` などのイテレーターを想定した構文でイテレーターを使用可能にする、かなり一般的なテクニックです。

```js
let i = 1;

const iterator = {
  next() {
    if (i <= 3) {
      return { value: i++, done: false };
    }
    return { value: undefined, done: true };
  },
  [Symbol.iterator]() {
    return this;
  },
};

for (const value of iterator) {
  console.log(value);
}
// 1
// 2
// 3
```

### ジェネレーターに対する反復処理

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

const generator = source();

for (const value of generator) {
  console.log(value);
}
// 1
// 2
// 3
```

### 早期の脱出

最初のループで `break` ステートメントを実行すると、ループが早期に終了します。イテレーターはまだ完了していないので、2 つ目のループは最初のループが停止したところから継続されます。

```js
const source = [1, 2, 3];

const iterator = source[Symbol.iterator]();

for (const value of iterator) {
  console.log(value);
  if (value === 1) {
    break;
  }
  console.log("この文字列はログ出力されません。");
}
// 1

// 同じイテレーターを使用する別のループは、
// 最後のループが終わったところをピックアップします。
for (const value of iterator) {
  console.log(value);
}
// 2
// 3

// イテレーターを使い切りました。
// このループでは、反復処理は実行されません。
for (const value of iterator) {
  console.log(value);
}
// [出力なし]
```

ジェネレーターは `return()` メソッドを実装しており、ループが終了するとジェネレーター関数が早期復帰するように発生しています。このため、ジェネレータはループ間で再利用することができません。

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

const generator = source();

for (const value of generator) {
  console.log(value);
  if (value === 1) {
    break;
  }
  console.log("この文字列はログ出力されません。");
}
// 1

// イテレーターを使い切りました。
// このループでは、反復処理は実行されません。
for (const value of generator) {
  console.log(value);
}
// [出力なし]
```

### for...of と for...in との違い

`for...in` および `for...of` 文は、両方とも何かに対する繰り返しです。これらの主な違いは、何に対する繰り返しなのかというところです。

`for...in` 文は、オブジェクトのすべての列挙可能なプロパティに対して、順序不定で繰り返し処理を行います。`for...of` 文は、反復可能なオブジェクトが定義した順序で値を反復処理します。

次の例では、`Array` に対して `for...of` ループと `for...in` ループを使用した場合の違いを示しています。

```js
Object.prototype.objCustom = function () {};
Array.prototype.arrCustom = function () {};

const iterable = [3, 5, 7];
iterable.foo = "hello";

for (const i in iterable) {
  console.log(i);
}
// "0", "1", "2", "foo", "arrCustom", "objCustom"

for (const i in iterable) {
  if (Object.hasOwn(iterable, i)) {
    console.log(i);
  }
}
// "0" "1" "2" "foo"

for (const i of iterable) {
  console.log(i);
}
// 3 5 7
```

オブジェクト `iterable` は `objCustom` および `arrCustom` プロパティを継承しています。`Object.prototype` および `Array.prototype` の各プロパティを継承とプロトタイプチェーンで格納しているからです。

`for...in` ループは `iterable` オブジェクトの列挙可能なプロパティのみを出力します。配列の要素である `3`, `5`, `7` や `"hello"` は、列挙可能なプロパティではないため出力しません。これらは値です。配列の *添字* が `arrCustom` や `objCustom` と共に出力されます。なぜプロパティが反復処理に出てこないのかが分からない場合は、配列の反復処理と `for...in` にもっと詳しい説明があります。

2 番目のループは最初のものと似ていますが、`Object.hasOwn()` を使用して見つかった列挙可能なプロパティがオブジェクト自身のものであるか、すなわち継承したものでないかどうかをチェックしています。オブジェクト自身のプロパティである場合は、ログ出力します。`0`, `1`, `2`, `foo` は自身のプロパティであるため出力されます。`arrCustom` と `objCustom` は継承されたものであるために出力されません。

このループは、`iterable` が反復可能オブジェクトとして定義している順序で *値* を反復処理し、ログ出力します。オブジェクトの *要素* である `3`, `5`, `7` は表示されますが、オブジェクトの *プロパティ* は表示されません。

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-for-in-and-for-of-statements |

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

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

関連情報
----

* `Array.prototype.forEach()`
* `Map.prototype.forEach()`
* `Object.entries()` – オブジェクトに `for...of` を使用するときに便利です。


import - JavaScript

import
======

静的な **`import`** 宣言は、他のモジュールによってエクスポートされた読み込み専用のライブバインディングをインポートするために使用します。インポートしたバインディングは、バインディングをエクスポートしたモジュールによって更新される一方、インポートしているモジュールによって再代入することができないために、「*ライブバインディング*」と呼ばれています。

ソースファイルの中で `import` 宣言を使用するためには、ランタイムがそのファイルをモジュールと見なす必要があります。HTML では、`<script>` タグに `type="module"` を加えることがこれに相当します。モジュールは、宣言するかどうかにかかわらず、 `Strict モード`になります。

また、`type="module"` のスクリプトを必要としない動的な **`import()`** という関数のようなものもあります。

構文
--

```js
import defaultExport from "module-name";
import \* as name from "module-name";
import { export1 } from "module-name";
import { export1 as alias1 } from "module-name";
import { default as alias } from "module-name";
import { export1, export2 } from "module-name";
import { export1, export2 as alias2, /\* … \*/ } from "module-name";
import { "string name" as alias } from "module-name";
import defaultExport, { export1, /\* … \*/ } from "module-name";
import defaultExport, \* as name from "module-name";
import "module-name";
```

`defaultExport`

モジュールからのデフォルトのエクスポートを参照する名前。JavaScript の識別子として有効な文字列でなければなりません。

`module-name`

インポートするモジュール。この指定子はホストが示した方法で評価されます。こちらはしばしばモジュールを含む `.js` ファイルへの相対または絶対 URL となっています。Node では、拡張子なしのインポートは `node_modules` におけるパッケージへの参照であることが多いです。バンドラーによっては、拡張子を省略してもよいことにしています。環境を確認してください。シングルクォートやダブルクォートで囲った文字列だけが使えます。

`name`

インポートを参照するとき名前空間のように用いられるモジュールオブジェクトの名前。JavaScript の識別子として有効な文字列でなければなりません。

`exportN`

インポートするエクスポートの名前。`module-name` のモジュールがエクスポートしている内容によって、識別子にも文字列リテラルにもどちらにもなりえます。文字列リテラルの場合、有効な識別子を用いて別名を割り当てなければなりません。

`aliasN`

指定されたインポートを参照する名前。JavaScript の識別子として有効な文字列でなければなりません。

説明
--

`import` 宣言はモジュールのトップレベル（要するにブロックや関数などの中以外）にのみ書くことができます。パーサーが `import` 宣言をモジュール以外の文脈（例えば `type="module"` のない `<script>` タグ、 `eval`、 `new Function` など、「スクリプト」や「関数の本体」をパース時の目標として持つもの） で検出すると、`SyntaxError` を発生させます。モジュール以外の文脈でモジュールをロードするには、ダイナミックインポートという構文を代わりに使用してください。

インポートされたすべてのバインディングは、同じスコープに複数存在してはいけません。これは `let` や `const`、 `class`、 `function`、 `var`、それから `import` といった、他のあらゆる宣言と同様です。

`import` 宣言は構文的に硬直したものとなっています。例えば、文字列リテラルしか指定子に使えなかったり、トップレベルでしか使用できなかったり、すべてのバインディングが識別子でなければならない、といった制限があります。この制限により、モジュールは評価する前に静的に解析してリンクさせることができます。これはモジュールを非同期にロードする上で鍵となる性質で、トップレベル await といった機能を実現させてくれています。

`import` 宣言には 4 つの形式があります:

* 名前付き import: `import { export1, export2 } from "module-name";`
* デフォルトの import: `import defaultExport from "module-name";`
* 名前空間の import: `import * as name from "module-name";`
* 副作用の import: `import "module-name";`

構文の意味を明らかにするため、下記に例を示します。

### 名前付き import

例えば `my-module` から `myExport` という名前の値が（`export * from "another.js"` などで暗黙的にせよ、 `export` 文で明示的にせよ）エクスポートされている場合、次の例では `myExport` を現在のスコープに追加します。

```js
import { myExport } from "/modules/my-module.js";
```

一つのモジュールから複数の名前をインポートすることもできます。

```js
import { foo, bar } from "/modules/my-module.js";
```

インポートする際、エクスポートされている名前を変更することもできます。例えば次のように書くと、 `shortName` を現在のスコープに追加します。

```js
import { reallyReallyLongModuleExportName as shortName } from "/modules/my-module.js";
```

モジュールからエクスポートされている名前が、識別子としては無効な文字列リテラルになっていることがあります。その場合対象の名前を現在のスコープで使用するには、別名を付けなければなりません。

```js
// /modules/my-module.js
const a = 1;
export { a as "a-b" };
```

```js
import { "a-b" as a } from "/modules/my-module.js";
```

**メモ:** `import { x, y } from "mod"` は、 `import defaultExport from "mod"` して `defaultExport` から `x` と `y` を分割代入することと等価ではありません。名前付きのインポートとデフォルトのインポートは JavaScript のモジュールにおける別種の構文です。

### デフォルトの import

デフォルトエクスポートでエクスポートされた値は、対応するデフォルトのインポート構文を用いてインポートする必要があります。最も単純なバージョンでは、デフォルトの値を直接インポートします:

```js
import myDefault from "/modules/my-module.js";
```

デフォルトのエクスポートは名前を明示していませんので、好きな名前を与えることができます。

デフォルトのインポートと名前空間のインポート、または名前付きインポートを一緒に使用することもできます。そのような場合、デフォルトのインポートを最初に宣言してください。例えば次のとおり:

```js
import myDefault, \* as myModule from "/modules/my-module.js";
// myModule.default と myDefault は同じ値
```

あるいは:

```js
import myDefault, { foo, bar } from "/modules/my-module.js";
```

`default` という名前のインポートとデフォルトのインポートは、同じ結果をもたらします。ただし `default` は予約語なので、別名を付けなければなりません。

```js
import { default as myDefault } from "/modules/my-module.js";
```

### 名前空間の import

次のコードは、 `/modules/my-module.js` という場所にあるモジュールがエクスポートするすべての値を含んだ `myModule` を現在のスコープに追加します。

```js
import \* as myModule from "/modules/my-module.js";
```

この場合、 `myModule` は*名前空間*オブジェクトを表しています。名前空間オブジェクトはエクスポートされているすべての値をプロパティとして保持しています。例えば、上記のコードでインポートされたモジュールが `doAllTheAmazingThings()` をエクスポートしていた場合、次のように呼ぶことができます:

```js
myModule.doAllTheAmazingThings();
```

`myModule` は `null` prototype とする封印されたオブジェクトです。 デフォルトのエクスポートは `default` という名前のキーで利用できるようになっています。詳細はモジュール名前空間オブジェクトをご覧ください。

>
> **メモ**: JavaScript は `import * from "module-name"` のような、ワイルカードインポートを提供していません。名前の衝突が高確率で発生するためです。
>
>
>

### 副作用のためだけにモジュールをインポートする

副作用のためだけにモジュール全体をインポートした場合、何もインポートされません。モジュールのグローバルなコードが実行されるだけで、値はインポートされないのです。

```js
import "/modules/my-module.js";
```

この種のインポートはしばしばポリフィルのために用いられます。ポリフィルはグローバル変数を書き換えるからです。

例
-

### 標準的なインポート

こちらの例では、指定した範囲内におけるすべての素数を取得する関数をエクスポートする、再利用可能なモジュールを作ります。

```js
// getPrimes.js
/\*\*
 \* `max` より小さな素数のリストを返す。
 \*/
export function getPrimes(max) {
  const isPrime = Array.from({ length: max }, () => true);
  isPrime[0] = isPrime[1] = false;
  isPrime[2] = true;
  for (let i = 2; i \* i < max; i++) {
    if (isPrime[i]) {
      for (let j = i \*\* 2; j < max; j += i) {
        isPrime[j] = false;
      }
    }
  }
  return [...isPrime.entries()]
    .filter(([, isPrime]) => isPrime)
    .map(([number]) => number);
}
```

```js
import { getPrimes } from "/modules/getPrimes.js";

console.log(getPrimes(10)); // [2, 3, 5, 7]
```

### インポートした値はエクスポートしたモジュールだけが変更できる

インポートした識別子は「ライブバインディング」と呼ばれます。エクスポートしているモジュールが再代入するとインポートしている値も変わるからです。しかしながら、当の変数をインポートしているモジュールは再代入できません。それでも、エクスポートしたオブジェクトを保持しているモジュールは、インポートしたオブジェクトを書き換えることができますし、変更した値は同じ値をインポートしているすべてのモジュールが観測できるようになっています。

値の変更は モジュール名前空間オブジェクトを通じて観測することもできます。

```js
// my-module.js
export let myValue = 1;
setTimeout(() => {
  myValue = 2;
}, 500);
```

```js
// main.js
import { myValue } from "/modules/my-module.js";
import \* as myModule from "/modules/my-module.js";

console.log(myValue); // 1
console.log(myModule.myValue); // 1
setTimeout(() => {
  console.log(myValue); // 2; my-module has updated its value
  console.log(myModule.myValue); // 2
  myValue = 3; // TypeError: Assignment to constant variable.
  // インポートしているモジュールができるのは値を読むことだけで、再代入はできません。
}, 1000);
```

仕様
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-imports |

ブラウザー実装状況
---------

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

関連情報
----

* `export`
* `import.meta`
* Limin Zhu, Brian Terlson and Microsoft Edge Team: Previewing ES6 Modules and more from ES2015, ES2016 and beyond
* Hacks blog post by Jason Orendorff: ES6 in Depth: Modules
* Hacks blog post by Lin Clark: ES modules: A cartoon deep-dive
* Axel Rauschmayer's book: "Exploring JS: Modules"
* The Modern JavaScript Tutorial(javascript.info): Export and Import


function 宣言 - JavaScript

function 宣言
===========

**`function`** 宣言は、指定された引数を使用して関数を定義します。

また、 `Function` のコンストラクターと関数式を使用して関数を定義することもできます。

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

構文
--

```js
function name(param0) {
  statements
}
function name(param0, param1) {
  statements
}
function name(param0, param1, /\* … ,\*/ paramN) {
  statements
}
```

`name`

関数の名前です。

`param` 省略可

関数に渡す引数の名前です。引数の最大数はエンジンによって異なります。

`statements` 省略可

関数の本体を構成する文です。

解説
--

関数宣言で作成された関数は `Function` オブジェクトであり、`Function` オブジェクトのすべてのプロパティ、メソッド、動作を備えています。関数の詳細については `Function` を参照してください。

関数は式を使用して作成することもできます (関数式を参照)。

既定では、関数は `undefined` を返します。他の値を返すには、関数に返す値を指定する `return` 文が必要です。

### 条件付きで作成される関数

**警告:** 厳格モードではない場合、ブロック内での関数宣言は奇妙な動きをします。ブロック内での関数宣言は、厳格モード時のみ行ってください。

関数は条件付きで宣言できます。つまり、関数文を `if` 文の中に入れ子にすることができますが、結果は実装によって一貫性がないので、このパターンを本番コードでは使用すべきではありません。条件付きの関数の作成には、代わりに関数式を使用してください。

```js
console.log(
  `'foo' name ${
 "foo" in globalThis ? "is" : "is not"
 } global. typeof foo is ${typeof foo}`,
);
if (false) {
  function foo() {
    return 1;
  }
}

// In Chrome:
// 'foo' の名前はグローバル。typeof foo は undefined
//
// In Firefox:
// 'foo' の名前はグローバル。typeof foo は undefined
//
// In Safari:
// 'foo' の名前はグローバル。typeof foo は function
```

`if` 本体が実際に実行されるかどうかにかかわらず、スコープと巻き上げの効果は変わりません。

```js
console.log(
  `'foo' name ${
 "foo" in globalThis ? "is" : "is not"
 } global. typeof foo is ${typeof foo}`,
);
if (true) {
  function foo() {
    return 1;
  }
}

// In Chrome:
// 'foo' の名前はグローバル。typeof foo は undefined
//
// In Firefox:
// 'foo' の名前はグローバル。typeof foo は undefined
//
// In Safari:
// 'foo' の名前はグローバル。typeof foo は function
```

厳格モードでは、ブロックレベルの関数宣言はそのブロックのスコープとなり、そのブロックの先頭に巻き上げられます。

```js
"use strict";

{
  foo(); // Logs "foo"
  function foo() {
    console.log("foo");
  }
}

console.log(
  `'foo' name ${
 "foo" in globalThis ? "is" : "is not"
 } global. typeof foo is ${typeof foo}`,
);
// 'foo' name is not global. typeof foo is undefined
```

### 関数宣言の巻き上げ

JavaScript の関数宣言は、それを囲む関数やグローバルスコープの先頭に巻き上げられ、関数を宣言する前に使うことができます。

```js
hoisted(); // "foo" とログ出力

function hoisted() {
  console.log("foo");
}
```

関数式は巻き上げられないことに注意してください。

```js
notHoisted(); // TypeError: notHoisted is not a function

var notHoisted = function () {
  console.log("bar");
};
```

例
-

### function の使用

以下のコードは、3 つの商品の販売個数が指定されたときに、売上の合計額を返す関数を宣言しています。

```js
function calcSales(unitsA, unitsB, unitsC) {
  return unitsA \* 79 + unitsB \* 129 + unitsC \* 699;
}
```

仕様書
---

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

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

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

関連情報
----

* `Function`
* 関数式
* function\* 文
* function\* 式
* アロー関数
* `GeneratorFunction`
* 非同期関数
* 非同期関数式


async function* - JavaScript

async function\*
================

**`async function*`** 宣言は非同期ジェネレーター関数を定義し、これは `AsyncGenerator` オブジェクトを返します。

非同期ジェネレーター関数は、`AsyncGeneratorFunction` コンストラクターや `async function*` 式の構文を使用して定義することもできます。

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

構文
--

```js
async function\* name(param0) {
  statements
}
async function\* name(param0, param1) {
  statements
}
async function\* name(param0, param1, /\* … ,\*/ paramN) {
  statements
}
```

**メモ:** 非同期ジェネレーター関数には、対応するアロー関数はありません。

### 引数

`name`

関数名です。

`param` 省略可

関数の構文上の引数名です。

`statements` 省略可

関数の本体を構成する文です。

解説
--

非同期ジェネレーター関数は、非同期関数とジェネレーター関数の機能を組み合わせたものです。関数の内部で `await` と `yield` のキーワードの両方を使うことができます。これにより、ジェネレーター関数の遅延の性質を利用しながら、`await` で人間工学的に非同期タスクを処理することができるようになります。

`function*` で宣言された通常のジェネレーター関数とは異なり、非同期ジェネレーター関数は `AsyncGenerator` オブジェクトを返します。非同期反復可能プロトコルに準拠しています。`next()` を呼び出すたびに、イテレーターの結果オブジェクトに解決する `Promise` を返します。

非同期ジェネレーターからプロミスが生成されると、イテレーターの結果のプロミスの最終的な状態は、生成されたプロミスの状態と一致します。例えば次のようになります。

```js
async function\* foo() {
  yield Promise.reject(1);
}

foo()
  .next()
  .catch((e) => console.error(e));
```

生成されたプロミスが拒否された場合、イテレーターの結果も拒否されるため、`1` がログ出力されます。非同期ジェネレーターの解決結果の `value` プロパティは、別のプロミスにはなりません。

`async function*` 宣言は、そのスコープの先頭に巻き上げされ、そのスコープ内のどこでも呼び出すことができます。

例
-

### 非同期ジェネレーター関数の宣言

非同期ジェネレーター関数は、常に結果のプロミスを生成します。それぞれの `yield` 手順が同期的であってもです。

```js
async function\* myGenerator(step) {
  await new Promise((resolve) => setTimeout(resolve, 10));
  yield 0;
  yield step;
  yield step \* 2;
}

const gen = myGenerator(2);
gen
  .next()
  .then((res) => {
    console.log(res); // { value: 0, done: false }
    return gen.next();
  })
  .then((res) => {
    console.log(res); // { value: 2, done: false }
    return gen.next();
  })
  .then((res) => {
    console.log(res); // { value: 4, done: false }
    return gen.next();
  })
  .then((res) => {
    console.log(res); // { value: undefined, done: true }
    return gen.next();
  });
```

### 非同期ジェネレーター関数を用いて一連のファイルを読み込む

この例では、Node の `fs/promises` モジュールを使用して、一連のファイルを読み、リクエストされたときだけそのコンテンツにアクセスするようにしています。

```js
async function\* readFiles(directory) {
  const files = await fs.readdir(directory);
  for (const file of files) {
    const stats = await fs.stat(file);
    if (stats.isFile()) {
      yield {
        name: file,
        content: await fs.readFile(file, "utf8"),
      };
    }
  }
}

const files = readFiles(".");
console.log((await files.next()).value);
// Possible output: { name: 'file1.txt', content: '...' }
console.log((await files.next()).value);
// Possible output: { name: 'file2.txt', content: '...' }
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-async-generator-function-definitions |

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

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

関連情報
----

* `async function*` 式
* `AsyncGeneratorFunction` オブジェクト
* イテレータープロトコル
* `GeneratorFunction` オブジェクト
* `yield`
* `yield*`
* `Function` オブジェクト
* 関数


for...in - JavaScript

for...in
========

**`for...in` 文**は、キーが文字列であるオブジェクトの列挙可能プロパティすべてに対して、継承された列挙可能プロパティも含めて反復処理を行います (Symbol がキーになったものは無視します)。

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

構文
--

```js
for (variable in object)
  statement
```

### 引数

`variable`

それぞれの反復処理において、文字列でプロパティ名を受け取ります。`const`、`let`、`var` の何れかの宣言、または代入ターゲット（例えば、以前宣言された変数や、オブジェクトプロパティ）です。

`object`

シンボルではない列挙可能なプロパティを反復処理するオブジェクトです。

`statement`

それぞれの反復処理で実行される文です。 `variable` を参照することができます。ブロック文を使用して、複数の文を使用することができます。

解説
--

このループは、オブジェクト自身と、オブジェクトがそのプロトタイプチェーンから継承するプロパティ（プロトタイプチェーンにおいて、オブジェクトから遠いプロトタイプのプロパティよりも、近いプロトタイプのプロパティが優先される）のすべての列挙可能なプロパティを反復処理することになります。

`for...in` ループは、列挙可能なシンボル以外のプロパティに対してのみ反復処理を行います。 `Array` や `Object` のような組み込みコンストラクターから生成したオブジェクトは、列挙可能でないプロパティを `Array.prototype` や `Objet.prototype` から、例えば `Array` の `indexOf()` メソッドや `Object` の `toString()` メソッドを継承していますが、これらは `for...in` ループでは処理されません。

現代の ECMAScript の仕様では、走査順序は明確に定義されており、 実装同士の間で一貫しています。プロトタイプチェーンのそれぞれの成分内では、非負の整数値（配列の添字となるもの）はすべて値の昇順で最初に走査され、次に文字列のキーがプロパティの作成時系列で昇順に走査されます。

`for...in` の `variable` 部分は、`=` 演算子の前に来ることができるものであれば、何でも受け入れることができます。ループ本体の中で再代入されない限り、`const` を使用して変数を宣言できます（これらは反復処理毎に別々の変数と見なされるため、変化が可能です）。そうでない場合は、`let` を使用してください。分割代入 や `for (x.y in iterable)` のようなオブジェクトプロパティを使用することもできます。

古い構文では、初期化子付きのループ変数を `var` 宣言で行うことができます。これは厳格モードでは構文エラーが発生し、非厳格モードでは無視されます。

### 削除、追加、変更されたプロパティ

プロパティがある反復処理で変更され、その後に処理された場合は、ループでの値はその後の時点での値となります。処理される前に削除されたプロパティは、その後処理されません。反復処理が行われているオブジェクトに追加されたプロパティは、処理されたり、反復処理から除外されたりします。

一般的に、現在処理しているプロパティ以外のものに関しては、反復の間にオブジェクトのプロパティを追加、修正、または削除しないのが一番です。追加したプロパティが処理されるか、(現在のもの以外の)修正したプロパティが修正される前または後に処理されるか、または削除したプロパティが削除される前に処理されるかといったことには、何の保証もありません。

### 配列の反復処理と for...in

配列の添字は整数名を持つ単なる列挙可能なプロパティであり、それ以外は一般的なオブジェクトのプロパティと同じです。`for...in` ループは、すべての整数キーを他のキーの前に、厳密に増加する順序で反復処理するので、`for...in` の動作は通常の配列の反復処理に近いものです。しかし、`for...in` ループは、非整数の名前を持つプロパティや継承されるプロパティも含めて、列挙可能なすべてのプロパティを返します。`for...of` とは異なり、`for...in` は配列のイテレーターの代わりにプロパティの列挙を使用します。疎配列では、`for...of` は空のスロットにアクセスしますが、`for...in` はそうではありません。

数値の添字を使った `for` ループ（か `Array.prototype.forEach()` か `for...of` ループ）を使った方が、文字列ではなく数値の添字を返し、インデックス以外のプロパティを避けることができるので適しています。

### 固有のプロパティだけで繰り返す

オブジェクトのプロトタイプではなく、オブジェクト自体に付属するプロパティのみを考えたい場合は、以下のテクニックを使用することができます。

* `Object.keys(myObject)`
* `Object.getOwnPropertyNames(myObject)`

`Object.keys` は列挙可能な自分自身の文字列プロパティのリストを返す一方、 `Object.getOwnPropertyNames` は列挙可能でないプロパティも格納します。

多くの JavaScript スタイルガイドやリンターは、`for...in` の使用を推奨していません。なぜなら、プロトタイプチェーン全体を反復処理するので、望んだ結果になることはほとんどなく、より広く使用されている `for...of` ループと混同してしまう可能性があるからです。`for...in` の最も実用的な用途はデバッグで、（コンソールに出力するなどして）オブジェクトのプロパティを調べるのに簡単な方法でしょう。オブジェクトがアドホックなキーと値のペアとして使用されるような状況では、`for...in`によって、それらのキーのいずれかが具体的な値を保持しているかどうかを調べることができます。

例
-

### for...in の使用

以下の `for...in` ループは、オブジェクトの列挙可能なシンボルではないプロパティをすべて反復し、そのプロパティ名と値を文字列で記録します。

```js
const obj = { a: 1, b: 2, c: 3 };

for (const prop in obj) {
  console.log(`obj.${prop} = ${obj[prop]}`);
}

// ログ:
// "obj.a = 1"
// "obj.b = 2"
// "obj.c = 3"
```

### 自身のプロパティの反復処理

次の関数では `Object.hasOwn()` の使い方を例示しています。継承されたプロパティは表示されません。

```js
const triangle = { a: 1, b: 2, c: 3 };

function ColoredTriangle() {
  this.color = "red";
}

ColoredTriangle.prototype = triangle;

const obj = new ColoredTriangle();

for (const prop in obj) {
  if (Object.hasOwn(obj, prop)) {
    console.log(`obj.${prop} = ${obj[prop]}`);
  }
}

// ログ:
// "obj.color = red"
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-for-in-and-for-of-statements |

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

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

関連情報
----

* `for...of`
* `for`
* プロパティの列挙可能性と所有権
* `Object.getOwnPropertyNames()`
* `Object.hasOwn()`
* `Array.prototype.forEach()`


const - JavaScript

const
=====

**`const`** 宣言はブロックスコープのローカル変数（定数）を宣言します。定数の値は代入演算子を使用して再代入することができませんが、定数がオブジェクトであった場合、そのプロパティを追加したり、更新したり、削除したりすることができます。

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

構文
--

```js
const name1 = value1;
const name1 = value1, name2 = value2;
const name1 = value1, name2 = value2, /\* …, \*/ nameN = valueN;
```

`nameN`

宣言する変数名。それぞれ、正当な JavaScript 識別子または分割結合パターンでなければなりません。

`valueN`

変数の初期値。正式な式であれば何でもかまいません。

解説
--

`const` 宣言んは `let` とよく似ています。

* `const` declarations are scoped to blocks as well as functions.
* `const` 宣言は宣言した位置に到達してからでないとアクセスすることができません（一時的デッドゾーンを参照してください）。このため、 `const` 宣言は一般的に巻き上げされないと見なされます。
* スクリプトの最上位で宣言された場合、 `const` 宣言は `globalThis` にプロパティを作成しません。
* `const` 宣言は、同じスコープ内の他の宣言によって再宣言することはできません。
* `const` は文ではなく宣言を始めます。つまり、ブロックの本体として単独の `const` 宣言を使用することはできません（変数にアクセスする方法がないので、意味はあります）。

```js
if (true) const a = 1; // SyntaxError: Lexical declaration cannot appear in a single-statement context
```

定数の初期化子が必要です。同じ宣言の中でその値を指定しなければなりません。（後で変更できないことを考えると、これは意味のあることです。）

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

`const` 宣言は値への不変の参照を作成します。これはその値が不変であるという意味ではなく、変数の識別子が再割り当てできないという意味です。例えば、内容がオブジェクトの場合、これはオブジェクトの内容（例えばプロパティ）は変更できることを意味しています。 `const` 宣言は「アイデンティティが一定の変数を作成する」のであって、「値が一定の変数を作成する」のではありません。また、「不変のバインド」を作成するのであって、「不変の値」を作成するのではありません。

多くのスタイルガイド（MDN のものも含む）では、変数がそのスコープで再代入されない場合は、 `const` を `let` の代わりに使用することを推奨しています。これにより、変数の型（プリミティブの場合は値）が変更されることはないという意図が明確になります。他にも、プリミティブ以外の変数が変更される場合は `let` を推奨する人もいます。

`const` キーワードに続くリストはバインディングリストと呼ばれ、カンマで区切られます。カンマはカンマ演算子ではなく、 `=` は代入演算子ではありません。後の変数の初期化子は、リスト内の前の変数を参照することができます。

例
-

### 基本的な定数の使い方

定数は大文字または小文字で宣言することができますが、特にプリミティブの場合は、本当に変更不可能であるので、すべて大文字で宣言するのが慣例です。

```js
// MY\_FAV を定数として定義して、その値を 7 にします
const MY\_FAV = 7;

console.log("my favorite number is: " + MY\_FAV);
```

```js
// Re-assigning to a constant variable throws an error
MY\_FAV = 20; // TypeError: Assignment to constant variable

// Redeclaring a constant throws an error
const MY\_FAV = 20; // SyntaxError: Identifier 'MY\_FAV' has already been declared
var MY\_FAV = 20; // SyntaxError: Identifier 'MY\_FAV' has already been declared
let MY\_FAV = 20; // SyntaxError: Identifier 'MY\_FAV' has already been declared
```

### ブロックスコープ

ブロックスコープの性質に注意することが重要です。

```js
const MY\_FAV = 7;

if (MY\_FAV === 7) {
  // これは問題なく、ブロックスコープの MY\_FAV 変数を作成します
  const MY\_FAV = 20;
  console.log(MY\_FAV); // 20

  // これはグローバルコンテキストに巻き上げられ、エラーが発生します
  var MY\_FAV = 20; // SyntaxError: Identifier 'MY\_FAV' has already been declared
}

console.log(MY\_FAV); // 7
```

### オブジェクトと配列の定数

`const` はオブジェクトや 配列にも作用します。オブジェクトを上書きしようとすると、"Assignment to constant variable" というエラーが発生します。

```js
const MY\_OBJECT = { key: "value" };
MY\_OBJECT = { OTHER\_KEY: "value" };
```

しかし、オブジェクトのキーは保護されていないので、次の文は問題なく実行されます。

```js
MY\_OBJECT.key = "otherValue";
```

オブジェクトを不変にするには、 `Object.freeze()` を使用する必要があります。

配列も同様です。新しい配列を変数に割り当て要とすると、"Assignment to constant variable" のエラーが発生します。

```js
const MY\_ARRAY = [];
MY\_ARRAY = ["B"];
```

しかし、配列にアイテムを追加することはでき、変更は可能です。

```js
MY\_ARRAY.push("A"); // ["A"]
```

### 分割代入による宣言

それぞれの `=` の左辺はバインドパターンにもなります。これにより、一度に複数の変数を作成することができます。

```js
const result = /(a+)(b+)(c+)/.exec("aaabcc");
const [, a, b, c] = result;
console.log(a, b, c); // "aaa" "b" "cc"
```

詳しくは、分割代入を参照してください。

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-let-and-const-declarations |

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

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

関連情報
----

* `var`
* `let`
* JavaScript ガイドの定数


do...while - JavaScript

do...while
==========

**`do...while`** 文は指定された文を、テスト条件が false に評価されるまで実行するループを作成します。条件は文を実行した後に評価されます。結果として、指定された文は少なくとも 1 回は実行されます。

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

構文
--

```js
do
  statement
while (condition);
```

`statement`

少なくとも 1 回は実行され、条件が真と評価されるたびに再実行される文。ループ内で複数の文を実行するには、それらの文をグループ化するためにブロック文 (`{ /* ... */ }`) を使ってください。

`condition`

ループを通過した後ごとに評価される式。もし `condition` が true に評価されるなら、`statement` は再度実行されます。`condition` が false に評価されるときは、制御が `do...while` に続く文へ渡ります。

メモ: `break` 文を使うと、`condition` が false と評価される前にループを停止することができます。

例
-

### `do...while` の使用

次の例では、 `do...while` ループを少なくとも 1 回は実行し、 `i` が 5 より小さいという条件を満たさなくなるまで反復します。

```js
let result = "";
let i = 0;
do {
  i += 1;
  result += `${i} `;
} while (i > 0 && i < 5);
// Despite i === 0 this will still loop as it starts off without the test

console.log(result);
```

### 条件として代入文を使用

場合によっては、条件として代入を使用することは意味があります。しかし、その場合、正しい方法と間違った方法があります。`while` のドキュメントでは、代入を条件として使用の節で、知っておくべき、そして従うべき一般的な良い実践例を示しています。

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-do-while-statement |

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

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

関連情報
----

* `while`
* `for`
* `break`
* `continue`


if...else - JavaScript

if...else
=========

**`if...else`** 文は、指定された条件が真値ならば文を実行します。条件が偽値なら、オプションの `else` 節にあるもう一方の文を実行します。

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

構文
--

```js
if (condition)
  statement1

// else 節付き
if (condition)
  statement1
else
  statement2
```

`condition`

真値または偽値と認識される式です。

`statement1`

*condition* が真値の場合に実行される文です。さらにネストされた `if` 文を含む、どんな文であってもかまいません。複数の文を実行するためには、それらの文をグループ化するためにブロック文 (`{ /* ... */ }`) を使用してください。実行する文がない場合は、空文を使用してください。

`statement2`

`condition` が偽値で、かつ `else` 節が存在するなら実行される文です。ブロック文およびさらにネストされた `if` 文を含む、どんな文であってもかまいません。

解説
--

複数の `if...else` 文をネストすることで、 `else if` 節を作成することができます。 JavaScript では（1 単語の）`elseif` キーワードがありませんので注意してください。

```js
if (condition1)
  statement1
else if (condition2)
  statement2
else if (condition3)
  statement3
// …
else
  statementN
```

これがどのように動作するか理解するために、ネストが適切にインデントされていたらどのように見えるかを示します。

```js
if (condition1)
  statement1
else
  if (condition2)
    statement2
  else
    if (condition3)
      statement3
// …
```

節の中で複数の文を実行するためには、それらの文をグループ化するためにブロック文 (`{ ... }`) を使ってください。

```js
if (condition) {
  statements1
} else {
  statements2
}
```

ブロックを使用しないと、特にコードが手作業で整形されている場合、混乱した動作になることがあります。

```js
function checkValue(a, b) {
  if (a === 1)
    if (b === 2)
      console.log("a is 1 and b is 2");
  else
    console.log("a is not 1");
}
```

このコードは何の問題もないように見えますが、`checkValue(1, 3)` を実行すると "a is not 1" というログを出力します。これは、dangling else の場合、`else` 節は最も近い `if` 節に接続されるからです。したがって、上記のコードを適切なインデントで記述すると、次のようになります。

```js
function checkValue(a, b) {
  if (a === 1)
    if (b === 2)
      console.log("a is 1 and b is 2");
    else
      console.log("a is not 1");
}
```

一般的な良い実践としては、常にブロック文を使用し、特に入れ子の `if` 文を含むコードでは、ブロック文を使用することをお勧めします。

```js
function checkValue(a, b) {
  if (a === 1) {
    if (b === 2) {
      console.log("a is 1 and b is 2");
    }
  } else {
    console.log("a is not 1");
  }
}
```

 プリミティブの論理値である `true` および `false` を `Boolean` オブジェクトの真性や偽性と混同しないでください。 `false`, `undefined`, `null`, `0`, `-0`, `NaN`, 空文字列 (`""`) のいずれでもない値、および任意のオブジェクトは（
 `false` の値を持つ Boolean オブジェクトを含め）、条件として使用されたときに真値と解釈されます。例えば以下のような場合です。

```js
const b = new Boolean(false);
if (b) {
  console.log("b is truthy"); // この条件式は truthy です
}
```

例
-

### if...else の使用

```js
if (cipherChar === fromChar) {
  result += toChar;
  x++;
} else {
  result += clearChar;
}
```

### else if の使用

JavaScript に `elseif` 構文はありませんので注意してください。 `else` と `if` の間に空白を置いて記述してください。

```js
if (x > 50) {
  /\* 何かを行う \*/
} else if (x > 5) {
  /\* 何かを行う \*/
} else {
  /\* 何かを行う \*/
}
```

### 条件式の中での代入

`x = y` のように代入を条件とする `if...else` を持つことは、稀であるはずです。

```js
if (x = y) {
  /\* 何かを行う \*/
}
```

しかし、稀にそのようなことをしたくなった場合、`while` のドキュメントの代入を条件として使用の節に、知っていて従うべき、一般的に良い実践を示した例を紹介しています。

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-if-statement |

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

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

関連情報
----

* `block`
* `switch`
* 条件演算子


ラベル - JavaScript

ラベル
===

**ラベル付き文**は、任意の文に接頭辞として識別子を付けたものです。ラベル付き文の中にネストされた `break` 文や `continue` 文を使用すると、このラベルにジャンプすることができます。

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

構文
--

```js
ラベル:
  文
```

`ラベル`

予約語ではない任意の JavaScript の識別子。

`文`

JavaScript の文。 `break` は任意のラベル付き文で使うことができ、 `continue` はループのラベル付き文で使うことができます。

解説
--

ラベルを使用して文を識別すると、後で `break` または `continue` 文を使用して参照することができます。JavaScript には `goto` 文がないことに注意してください。

ラベルを参照する `break` や `continue` は、`ラベル` によってラベル付けされた `文` 中になければなりません。`ラベル` は、`文` の範囲内でしか利用できない変数だと考えてください。

もし、`文` を実行中に `break ラベル;` 文に出会った場合、`文` の実行が終了し、ラベル付けされた文の直後の文から実行を続けます。

`continue ラベル;` は、`文` がループ文のうちの何れかである場合のみ使用できます。`continue ラベル;` 文が `文` の実行中に現れた場合、`文` の実行はループの次の反復処理に続きます。ラベルなしの `continue;` は最も内側のループのみを継続することができるのに対し、`continue ラベル;` はその文がほかのループの中にネストされていた場合でも、指定した任意のループの継続処理を行うことができます。

文に複数のラベルを付けることができます。この場合、ラベルはすべて機能的に同等になります。

例
-

### ラベル付き continue を for ループで使用

```js
// 最初の文は "loop1" というラベルが付いています
loop1: for (let i = 0; i < 3; i++) {
  // 2 番目の文は "loop2" というラベルが付いています
  loop2: for (let j = 0; j < 3; j++) {
    if (i === 1 && j === 1) {
      continue loop1;
    }
    console.log(`i = ${i}, j = ${j}`);
  }
}

// 結果:
// i = 0, j = 0
// i = 0, j = 1
// i = 0, j = 2
// i = 1, j = 0
// i = 2, j = 0
// i = 2, j = 1
// i = 2, j = 2
```

"i = 1, j = 1" と "i = 1, j = 2" をスキップしていることに注目してください。

### ラベル付き break を for ループで使用

```js
let i, j;

// 1 番目の for 文に "loop1" というラベルを付ける
loop1: for (i = 0; i < 3; i++) {
  // 2 番目の for 文に "loop2" というラベルを付ける
  loop2: for (j = 0; j < 3; j++) {
    if (i === 1 && j === 1) {
      break loop1;
    }
    console.log(`i = ${i}, j = ${j}`);
  }
}

// 結果:
// i = 0, j = 0
// i = 0, j = 1
// i = 0, j = 2
// i = 1, j = 0
```

前の `continue` の例との違いに注目してください。`break loop1` に遭遇すると、外側ループの実行が終了するので、"i = 1, j = 0" 以降のログ出力はありません。`continue loop1` に遭遇すると、外側ループの実行は次の反復処理で継続するので "i = 1, j = 1" だけスキップされます。

### ラベル付き continue 文の使用

配列 items と tests について、この例はすべてを tests に渡した items の数を数えます。

```js
// 1 から 100 までの数
const items = Array.from({ length: 100 }, (\_, i) => i + 1));
const tests = [
  { pass: (item) => item % 2 === 0 },
  { pass: (item) => item % 3 === 0 },
  { pass: (item) => item % 5 === 0 },
];
let itemsPassed = 0;

itemIteration: for (const item of items) {
  for (const test of tests) {
    if (!test.pass(item)) {
      continue itemIteration;
    }
  }

  itemsPassed++;
}
```

`continue itemIteration;` 文が、現在のアイテムに対する残りのテストと `itemsPassed` カウンターを更新する文をスキップして、次のアイテムに続けていることに注意してください。ラベル付けを使用しない場合は、代わりに論理値フラグを使用する必要があります。

```js
// 1 から 100 までの数
const items = Array.from({ length: 100 }, (\_, i) => i + 1));
const tests = [
  { pass: (item) => item % 2 === 0 },
  { pass: (item) => item % 3 === 0 },
  { pass: (item) => item % 5 === 0 },
];
let itemsPassed = 0;

for (const item of items) {
  let passed = true;
  for (const test of tests) {
    if (!test.pass(item)) {
      passed = false;
      break;
    }
  }
  if (passed) {
    itemsPassed++;
  }
}
```

### ラベル付き break 文を使用する

配列 items と tests について、このサンプルは items のすべてを tests に渡したかを判断します。

```js
// 1 から 100 までの数
const items = Array.from({ length: 100 }, (\_, i) => i + 1));
const tests = [
  { pass: (item) => item % 2 === 0 },
  { pass: (item) => item % 3 === 0 },
  { pass: (item) => item % 5 === 0 },
];
let allPass = true;

itemIteration: for (const item of items) {
  for (const test of tests) {
    if (!test.pass(item)) {
      allPass = false;
      break itemIteration;
    }
  }
}
```

この場合も、ラベルを使用しない場合は、代わりに論理値フラグを使用する必要があります。

```js
// 1 から 100 までの数
const items = Array.from({ length: 100 }, (\_, i) => i + 1));
const tests = [
  { pass: (item) => item % 2 === 0 },
  { pass: (item) => item % 3 === 0 },
  { pass: (item) => item % 5 === 0 },
];
let allPass = true;

for (const item of items) {
  let passed = true;
  for (const test of tests) {
    if (!test.pass(item)) {
      passed = false;
      break;
    }
  }
  if (!passed) {
    allPass = false;
    break;
  }
}
```

### break を使用したラベル付きブロックの使用

ラベルは単純なブロックでも使用することができますが、ループ以外のラベルは break 文のみが意味を持ちます。

```js
foo: {
  console.log("face");
  break foo;
  console.log("this will not be executed");
}
console.log("swap");

// Logs:
// "face"
// "swap"
```

### ラベル付き関数宣言

ラベルが適用できるのは文だけであり、宣言は含まれません。厳格モードでない場合、関数宣言をコードでラベル付けできる古い文法があります。

```js
L: function F() {}
```

ただし、厳格モードのコードでは `SyntaxError` が発生します。

```js
"use strict";
L: function F() {}
// SyntaxError: functions cannot be labelled
```

ジェネレーター関数や非同期関数は、厳格モードであってもなくてもラベル付けすることはできません。

```js
L: function\* F() {}
// SyntaxError: generator functions cannot be labelled
```

ラベル付きの関数電源の構文は非推奨であり、厳格モードでないコードであっても使用すべきではありません。実際、関数の本体の中からこのラベルへジャンプすることはできません。

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-labelled-statements |

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

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

関連情報
----

* `break`
* `continue`


class - JavaScript

class
=====

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
**`class`** 宣言は、プロトタイプベースの継承を使って、指定された名前の新しいクラスを作成します。

クラス式を使ってクラスを定義することもで、その場合は再定義やクラス名の省略ができます。同じスコープで**クラス宣言**を同じ名前で行おうとすると、`SyntaxError` が発生します。

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

構文
--

```js
class name [extends otherName] {
  // クラス本体
}
```

解説
--

クラス式と同様、クラス宣言の内部は厳格モードで実行されます。`constructor` メソッドは省略可能です。

クラス宣言は `let` や `const` と同様に動作し、巻き上げが行われません（関数宣言とは異なります）。

例
-

### 単純なクラス宣言

次の例では、はじめに `Rectangle` という名前のクラスを定義し、次にそれを拡張して `FilledRectangle` という名前のクラスを作成します。

なお、コンストラクター (`constructor`) で使われている `super()` は、コンストラクター内でのみ使えること、 `this` キーワードの使用*前*に呼び出さなくてはならないことに注意してください。

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

class FilledRectangle extends Rectangle {
  constructor(height, width, color) {
    super(height, width);
    this.name = "Filled rectangle";
    this.color = color;
  }
}
```

### クラスを二度宣言しようとする

クラス宣言を使って再度クラスを宣言すると、 `SyntaxError` が発生します。

```js
class Foo {}
class Foo {} // Uncaught SyntaxError: Identifier 'Foo' has already been declared
```

クラス式を使って事前にクラスを定義していたときも、同じエラーが発生します。

```js
let Foo = class {};
class Foo {} // Uncaught SyntaxError: Identifier 'Foo' has already been declared
```

Firefox のウェブコンソール (**ツール** > **ウェブ開発者** > **ウェブコンソール**) などの REPL で実験しているときに、同じ名前のクラス宣言を 2 つの入力で実行すると、同じ再宣言エラーが発生することがあります。この課題については、Firefox bug 1580891で詳しく議論されていますので、ご覧ください。Chrome コンソールでは、異なる REPL 入力間でのクラスの再宣言が可能です。

仕様書
---

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

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

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

関連情報
----

* `function` 宣言
* `class` 式
* クラス


for - JavaScript

for
===

**`for`** 文は、括弧で囲みセミコロンで区切った 3 つの引数と、続いてループ内で実行される文（ふつうはブロック文）から成るループを構成します。

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

構文
--

```js
for (initialization; condition; afterthought)
  statement
```

`initialization` 省略可

ループが始まる前に一度だけ評価される（代入式を含む）式または変数宣言。ふつうはカウンター変数を初期化するために使われます。この式では任意で、`var` キーワードを用いて新しい変数を宣言することもできます。`var` で宣言された変数はループ内のローカル変数にはなりません。すなわち、`for` ループが属するスコープと同じスコープになります。`let` で宣言された変数は文内のローカル変数になります。

この式の結果は捨て去られます。

`condition` 省略可

ループのそれぞれの反復処理が行われる前に評価される式です。この式が true と評価された場合は、 `statement` が実行されます。この式が false と評価された場合は、実行は `for` 構造に続く最初の式に飛びます。

この条件テストはオプションです。省略した場合、この条件は常に true と評価されます。

`afterthought` 省略可

ループのそれぞれの反復処理の最後に評価される式です。これは、次の `condition` の評価前に行われます。一般的には、カウンター変数を更新または増加するために使われます。

`statement`

条件が true と評価された場合に限り実行される文です。ループ内で複数の文を実行するには、ブロック文を使用して文をグループ化してください。ループ内で文を実行しないようにするには、空文 (`;`) を使用してください。

例
-

### for の使用

次の `for` 文は、変数 `i` を宣言し、それを `0` に初期化することから始まります。`i` が 9 より小さいことをチェックし、続く 2 つの文を実行し、ループを通過した後ごとに `i` を 1 増加します。

```js
for (let i = 0; i < 9; i++) {
  console.log(i);
  // その他の文
}
```

### 初期化ブロックの構文

初期化ブロックは、式と変数宣言の両方を受け入れることができます。ただし、式には括弧で囲んでいない `in` 演算子を使用することができません。`for...in` ループと曖昧になるためです。

```js
for (let i = "start" in window ? window.start : 0; i < 9; i++) {
  console.log(i);
}
// SyntaxError: 'for-in' loop variable declaration may not have an initializer.
```

```js
// Parenthesize the whole initializer
for (let i = ("start" in window ? window.start : 0); i < 9; i++) {
  console.log(i);
}

// Parenthesize the `in` expression
for (let i = ("start" in window) ? window.start : 0; i < 9; i++) {
  console.log(i);
}
```

### 省略可能な for の式

`for` ループの先頭にある 3 つの式は、省略可能です。例えば、`initialization` ブロックで変数を初期化する必要はありません。

```js
let i = 0;
for (; i < 9; i++) {
  console.log(i);
  // その他の文
}
```

`initialization` ブロックと同様に、`condition` ブロックも省略可能です。この式を省略した場合は、本体の中でループを脱出できるようにして、無限ループにならないようにしなければなりません。

```js
for (let i = 0; ; i++) {
  console.log(i);
  if (i > 3) break;
  // その他の文
}
```

3 つのブロックをすべて省略することもできます。繰り返しますが、 `break` 文を使用してループを終了させ、また break 文の条件がある時点で true になるように、変数を変更（増加）させていることを確認してください。

```js
let i = 0;

for (;;) {
  if (i > 3) break;
  console.log(i);
  i++;
}
```

しかし、3 つの位置の式をすべて使用する訳ではない場合、特に最初の式で変数を宣言せず、上位のスコープで何かを変更している場合は、代わりに `while` ループを使用することを検討したほうが意図がより明確になります。

```js
let i = 0;

while (i <= 3) {
  console.log(i);
  i++;
}
```

### 初期化ブロックの字句の宣言

初期化ブロック内で変数を宣言する場合、上位のスコープで宣言する場合と異なる点があり、特にループ本体内でクロージャを作成する場合は重要です。例えば、下記のコードを見てください。

```js
for (let i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i);
  }, 1000);
}
```

期待通り、`0`、`1`、`2` とログ出力します。しかし、その変数が上位スコープで定義されている場合は、

```js
let i = 0;
for (; i < 3; i++) {
  setTimeout(() => {
    console.log(i);
  }, 1000);
}
```

`3`、`3`、`3` とログ出力します。なぜかと言うと、それぞれの `setTimeout` が `i` 変数を閉じる新しいクロージャを作成しますが、`i` がループ本体のスコープでない場合、すべてのクロージャは最終的に呼び出されたときに同じ変数を参照します。そして `setTimeout` の非同期であるため、すでにループが終了した後に実行され、すべてのキューのコールバック本体の `i` は `3` という値になります。

これは、初期化に `var` 文を使用した場合にも起こります。`var` で宣言された変数は関数スコープのみで、レキシカルスコープにならない（つまり、ループ本体のスコープにすることはできない）からです。

```js
for (var i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i);
  }, 1000);
}
// 3, 3, 3 とログ出力
```

初期化ブロックのスコープ効果は、宣言がループ本体の中で行われ、たまたま `condition` と `afterthought` の部分でアクセス可能であるかのように理解することができます。より正確には、`let`宣言は `for` ループに特化されます。もし `initialization` が `let` 宣言であれば、ループ本体が評価された後、以下のことが毎回行われます。

1. 新しい字句スコープが作成され、新しい `let` が宣言された変数が追加されます。
2. 前回の反復処理でバインドされた値を用いて、新しい変数を再初期化します。
3. `afterthought` が新しいスコープで評価されます。

そのため、`afterthought` 内で新しい変数を割り当てても、前回反復処理したときのバインディングには影響しません。

クロージャを作成することで、特定の反復処理中のバインディングを取得することができます。このことから、`initialization` 節で作成したクロージャが、`afterthought` 節で `i` を再代入しても更新されないことがわかります。

```js
for (let i = 0, getI = () => i; i < 3; i++) {
  console.log(getI());
}
// Logs 0, 0, 0
```

これは、ループ本体の中で `getI` を宣言した場合のように "0, 1, 2" をログ出力するわけではありません。これは、`getI` が反復処理するたびに再評価されるのではなく、関数が一度作成され、（ループが最初に初期化されたときに宣言された変数を参照する）変数 `i` が閉じられるからです。その後、`i` の値を更新すると、実際には `i` という新しい変数が作成されますが、`getI` はそれを見ることができません。これを修正するには、`i` が更新されるたびに `getI` を再計算するようにします。

```js
for (let i = 0, getI = () => i; i < 3; i++, getI = () => i) {
  console.log(getI());
}
// Logs 0, 1, 2
```

実際、変数 `i` の最初のバインディングをキャプチャして、後でそれを割り当てることができます。この更新された値は、次の新しい `i` のバインディングを見るループ本体には見えません。

```js
for (
  let i = 0, getI = () => i, incrementI = () => i++;
  getI() < 3;
  incrementI()
) {
  console.log(i);
}
// Logs 0, 0, 0
```

これは "0, 0, 0" とログ出力します。なぜなら、各ループ評価における `i` 変数は実際には別個の変数ですが、`getI` と `incrementI` はどちらも `i` の*初期*バインディングを読み書きし、その後に宣言されたものには対応しないからです。

### 文を持たない for の使用

以下の `for` の繰り返しでは、 `final-expression` 句の中でにおけるノードのオフセット位置を検索しています。 `statement` 節を使用する必要がない場合は、代わりにセミコロンを使用してください。

```js
function showOffsetPos(id) {
  let left = 0;
  let top = 0;
  for (
    let itNode = document.getElementById(id); // 初期化
    itNode; // 条件式
    left += itNode.offsetLeft,
      top += itNode.offsetTop,
      itNode = itNode.offsetParent // 更新式
  ); // セミコロン

  console.log(
    `Offset position of "${id}" element:
left: ${left}px;
top: ${top}px;`,
  );
}

showOffsetPos("content");

// 出力結果:
// Offset position of "content" element:
// left: 0px;
// top: 153px;
```

`for` 文の後のセミコロンは必須であることに注意してください。これは空文としての役割を果たすからです。そうしないと、`for` 文は以下の `console.log` 行を `statement` 節として取得し、`log` を複数回実行させることになる。

### 2 つの反復用変数の使用

カンマ演算子を用いて、for ループで同時に更新される 2 つのカウンターを作成することができます。複数の `let` や `var` の宣言をカンマで結合することもできます。

```js
const arr = [1, 2, 3, 4, 5, 6];
for (let l = 0, r = arr.length - 1; l < r; l++, r--) {
  console.log(arr[l], arr[r]);
}
// 1 6
// 2 5
// 3 4
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-for-statement |

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

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

関連情報
----

* 空文
* `break`
* `continue`
* `while`
* `do...while`
* `for...in`
* `for...of`


式文 - JavaScript

式文
==

**式文**は、文を記述すべき場所で使用する式です。式は評価され、その結果は捨てられます。したがって、関数の実行や変数の更新など、副次的な効果のある式にのみ意味があります。

構文
--

```js
expression;
```

`expression`

評価する任意の式です。他の文と紛らわしい特定の式は曖昧ですので禁止されています。

解説
--

文専用の構文とは別に、ほとんどすべての式をそれ自体で文として使用することもできます。式の構文では、終わりにセミコロンが必要ですが、セミコロンがないために構文が不正になる場合は、自動セミコロン挿入で挿入されることがあります。

式は発生した後に破棄されるため、式の結果は利用できません。したがって、式が有益なものとなるためには、式に何か副次的な効果がある必要があります。式文は一般的に次のものです。

* 関数呼び出し (`console.log("Hello");`, `[1, 2, 3].forEach((i) => console.log(i));`)
* タグ付きテンプレートリテラル
* 代入式（複合演算子を含む）
* インクリメント／デクリメント演算子
* `delete`
* `import()`
* `yield` および `yield*`

他にも副次的な効果がある場合があるものとして、ゲッターの呼び出しや型変換の実行があります。

### 禁止されている式

式を文として使用するためには、他の文の構文とあいまいであってはいけません。したがって、式は以下のいずれかのトークンで始めてはいけません。

* `function`: `function` 宣言または `function*` 宣言となり、`function` 式または `function*` 式とはならない。
* `async function`: `async function` 宣言または `async function*` 宣言となり、`async function` 式または `async function*` 式とはならない。
* `class`: `class` 宣言となり、`class` 式にはならない。
* `let[`: `let` 宣言 の配列の分割代入となり、`let` 上のプロパティアクセサーにはならない（`let` は厳格モード以外でのみ識別子になる）
* `{`: ブロック文となり、オブジェクトリテラルにはなりません。

従って、以下のものは全て不正です。

```js
function foo() {
  console.log("foo");
}(); // SyntaxError: Unexpected token '('

// 何らか理由で、`let` という変数を作った
var let = [1, 2, 3];
let[0] = 4; // SyntaxError: Invalid destructuring assignment target

{
  foo: 1,
  bar: 2, // SyntaxError: Unexpected token ':'
};
```

さらに危険なことに、たまたま有効な構文であったとしても、意図しないコードになってしまうこともあります。

```js
// 何らか理由で、`let` という変数を作った
var let = [1, 2, 3];

function setIndex(index, value) {
  if (index >= 0) {
    // 配列 `let` に割り当てるつもりが、余計な変数を作成してしまう！
    let[index] = value;
  }
}

setIndex(0, [1, 2]);
console.log(let); // [1, 2, 3]

// これはオブジェクトリテラルではなくブロック文となり、
// `foo` はラベル、`1` は式文になる
// コンソールで起こることが多い
{ foo: 1 };
```

このような問題を避けるために、括弧を使用することで、一義的に式文となるようにすることができます。

```js
(function foo() {
  console.log("foo");
})();
```

例
-

### 制御フロー文の回避

制御フロー文の使用は、式文を使ってほとんど避けることができます。例えば、`if...else` は三項演算子や論理演算子に置き換えることができます。`for` や `for...of` のような反復処理文は、配列メソッドに置き換えることができます。

```js
// 制御フロー文の使用
function range(start, end) {
  if (start > end) {
    [start, end] = [end, start];
  }
  const result = [];
  for (let i = start; i < end; i++) {
    result.push(i);
  }
  return result;
}

// 式文の使用
function range2(start, end) {
  start > end && ([start, end] = [end, start]);
  return Array.from({ length: end - start }, (\_, i) => start + i);
}
```

**警告:** これは、言語の能力の一端を示すに過ぎません。制御フロー文の代用として式文を過剰に使用すると、コードの可読性が大幅に低下する可能性があります。

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-expression-statement |

関連情報
----

* 文と宣言
* 式と演算子


while - JavaScript

while
=====

**`while`** 文は、テスト条件が真と評価されている間、指定された文を実行するループを作成します。条件はその文を実行する前に評価されます。

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

構文
--

```js
while (condition)
  statement
```

`condition`

ループを通過するごとに、その前に評価される式。この条件が真と評価された場合は、 `statement` が実行されます。条件が偽と評価された場合は、実行は `while` ループの後の文に続きます。

`statement`

条件が真と評価されている間に実行される文。ループ内で複数の文を実行する場合は、ブロック文 (`{ /* ... */ }`) を使用してそれらの文をグループ化してください。

メモ: `break` 文を使用すると、条件が真と評価される前にループを停止することができます。

例
-

### while の使用

次の `while` ループは、 `n` が 3 より小さい間反復します。

```js
let n = 0;
let x = 0;

while (n < 3) {
  n++;
  x += n;
}
```

それぞれの反復で、ループは `n` を増加させ、それを `x` に加えます。したがって、 `x` および `n` は次の値をとります。

* 最初の通過の後: `n` = 1 および `x` = 1
* 2 回目の通過の後: `n` = 2 および `x` = 3
* 3 回目の通過の後: `n` = 3 および `x` = 6

3 回目の通過が完了した後、条件 `n` < 3 は真ではなくなり、ループは終了します。

### 代入を条件として使用

場合によっては、代入を条件として使用することに意味があることもあります。これは読みやすさとトレードオフの関係にあるので、このパターンを誰にでもわかりやすくするための、ある種の文体上の推奨事項があります。

次の例は、文書のコメントを反復処理し、コンソールにログ出力するものです。

```js
const iterator = document.createNodeIterator(document, NodeFilter.SHOW\_COMMENT);
let currentNode;
while (currentNode = iterator.nextNode()) {
  console.log(currentNode.textContent.trim());
}
```

これは完全によい例とは言えません。特に次の行があるからです。

```js
while (currentNode = iterator.nextNode()) {
```

その行の動作は、毎回コメントノードが得られるという点では問題ありません。

1. `iterator.nextNode()` がコメントノードを返し、それが `currentNode` に代入される。
2. `currentNode = iterator.nextNode()` の値は、従って真値となる。
3. そのため、`console.log()` の呼び出しを実行し、ループが継続される。

…そして、文書中にコメントノードがなくなったとき、次のようになります。

1. `iterator.nextNode()` は `null`` を返す。
2. 従って `currentNode = iterator.nextNode()` も `null` になり、これは偽値である。
3. そのため、ループを終了する。

この行の問題は、条件式にはふつう比較演算子、例えば `===` を使用するものですが、この行の `=` は比較演算子ではなく、代入演算子です。そのため、`=` は `===` の間違いのように見えてしまいます（実際には間違いではなくても）。

従って、このようにすると、一部のコードリンティングツール、例えば ESLint の `no-cond-assign` ルールなどは、誤記の可能性があるものを発見して修正しやすくするために、以下のような警告を報告します。

>
> Expected a conditional expression and instead saw an assignment.（条件式が期待されるところに代入がありました。）
>
>
>

多くのスタイルガイドでは、条件式に代入式を書くことが意図的であることを、より明確に示すことを推奨しています。それを行うための最小限の方法として、括弧をグループ化演算子として追加して代入式を囲む方法があります。

```js
const iterator = document.createNodeIterator(document, NodeFilter.SHOW\_COMMENT);
let currentNode;
while ((currentNode = iterator.nextNode())) {
  console.log(currentNode.textContent.trim());
}
```

実際、これは ESLint の `no-cond-assign` の既定値や Prettier で強制されているスタイルなので、このパターンをよく見かけるでしょう。

条件を明示的な比較に変えるために比較演算子を追加することを勧める人もいます。

```js
while ((currentNode = iterator.nextNode()) !== null) {
```

このパターンは他にも書き方があります。

```js
while ((currentNode = iterator.nextNode()) && currentNode) {
```

あるいは、`while` ループを使用するアイディアを完全に放棄する方法もあります。

```js
const iterator = document.createNodeIterator(document, NodeFilter.SHOW\_COMMENT);
for (
  let currentNode = iterator.nextNode();
  currentNode;
  currentNode = iterator.nextNode()
) {
  console.log(currentNode.textContent.trim());
}
```

読者が条件式のパターンとして代入式を記述することに十分に慣れていれば、これらの読みやすさはすべて同じくらいのはずです。そうでなければ、最も冗長ではありますが、最後の形式が最も読みやすいでしょう。

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-while-statement |

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

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

関連情報
----

* `do...while`
* `for`
* `break`
* `continue`


return - JavaScript

return
======

**`return`** 文は関数の実行を終了して、関数の呼び出し元に返す値を指定します。

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

構文
--

```js
return;
return expression;
```

`expression`

値が返される式。省略した場合は、代わりに `undefined` が返されます。

解説
--

`return` 文が関数本体の中で使用された際、その関数の実行が停止します。値を指定した場合、与えられた値が関数の呼び出し元に返されます。例として、以下の関数は引数 `x` が数値のとき、`x` の二乗を返します。

```js
function square(x) {
  return x \* x;
}
const demo = square(3);
// demo は 9 に等しい
```

値が省略された場合は、代わりに `undefined` が返されます。

以下の return 文はすべて関数の実行を中断するものです。

```js
return;
return true;
return false;
return x;
return x + y / 3;
```

### 自動セミコロン挿入

`return` 文は自動セミコロン挿入 (ASI) の影響を受けます。`return` キーワードと式の間の改行コードは許容されません。

```js
return
a + b;
```

上記のコードは ASI によって以下のように変換されます。

```js
return;
a + b;
```

コンソールは "unreachable code after return statement" と警告します。

**メモ:** Firefox 40 以降から `return` 文の後に到達不可能なコードが見つかった場合、コンソールに警告が表示されます。

括弧を使用することで、この問題を回避する（ASI を防ぐ）ことができます。

```js
return (
  a + b
);
```

例
-

### 関数を中断する

関数は `return` が呼び出された時点で即座に終了します。

```js
function counter() {
  // 無限ループ
  for (let count = 1; ; count++) {
    console.log(`${count}A`); // 5 まで
    if (count === 5) {
      return;
    }
    console.log(`${count}B`); // 4 まで
  }
  console.log(`${count}C`); // 決して現れない
}

counter();

// ログ:
// 1A
// 1B
// 2A
// 2B
// 3A
// 3B
// 4A
// 4B
// 5A
```

### 関数を返す

クロージャについての記事も参照のこと。

```js
function magic() {
  return function calc(x) {
    return x \* 42;
  };
}

const answer = magic();
answer(1337); // 56154
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-return-statement |

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

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

関連情報
----

* 関数
* クロージャ


break - JavaScript

break
=====

**`break`** 文は現在のループや `switch` 文を終了し、プログラムの制御を終了した文の次の文に移します。ラベル付きの文の中で使用された場合は、ラベル付きの文を飛び越えるためにも使われます。

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

構文
--

```js
break;
break label;
```

`label` 省略可

終了する文のラベルに関連付けられた識別子。`break` 文がループや `switch` の中に入れ子になっていない場合は、ラベル識別子が必要です。

解説
--

`break;` に遭遇すると、プログラムは最も内側の `switch` またはループ文から抜け出し、その次の文から実行を続けます。

`break label;` に遭遇すると、プログラムは `label` でラベル付けされた文から抜け出し、その次の文の実行を続けます。`break` 文は参照されるラベルの内側にある必要があります。ラベルはあらゆるブロック文に付けることができます。ループ文の前である必要はありません。

`break` 文は、その後にラベルがあるかどうかに関わらず、スクリプト、モジュール、関数の本体、静的初期化ブロックのそれぞれ最上位で使用することはできません。その関数やクラスがさらにループの中に含まれていた場合でもです。

例
-

### while ループにおける break

次の関数には `break` 文があり、`i` が `3` の時に `while` 文を終了させるので、`3 * x` の値を返します。

```js
function testBreak(x) {
  let i = 0;

  while (i < 6) {
    if (i === 3) {
      break;
    }
    i += 1;
  }

  return i \* x;
}
```

### switch 文における break

次のコードには、一致する case と対応するコードが実行された後で `switch` 文を終了するための `break` があります。

```js
const food = "sushi";

switch (food) {
  case "sushi":
    console.log("Sushi is originally from Japan.");
    break;
  case "pizza":
    console.log("Pizza is originally from Italy.");
    break;
  default:
    console.log("I have never heard of that dish.");
    break;
}
```

### ラベル付きブロックにおける break

次のコードは、ラベル付きブロックで `break` 文を使っています。`break outerBlock` を使用すると、制御は `outerBlock` としてマークされたブロック構文の末尾に移動します。

```js
outerBlock: {
  innerBlock: {
    console.log("1");
    break outerBlock; // innerBlock および outerBlock の両方から抜けます
    console.log(":-("); // スキップされる
  }
  console.log("2"); // スキップされる
}
```

### 構文違反の break 文

`break` 文は参照先のラベルの中になければなりません。次のコードもラベル付きブロックで `break` 文を使っていますが、`break` 文が `block2` を参照しているにもかかわらず `block2` の中にないので、構文エラーが発生します。

```js
block1: {
  console.log("1");
  break block2; // SyntaxError: label not found
}

block2: {
  console.log("2");
}
```

構文エラーは、次のコードのように `break` がループの中や、`break` 文によって脱出しようとしているラベル付きブロックの中で入れ子になっている関数で使われた場合にも、構文エラーが発生します。

```js
function testBreak(x) {
  let i = 0;

  while (i < 6) {
    if (i === 3) {
      (() => {
        break;
      })();
    }
    i += 1;
  }

  return i \* x;
}

testBreak(1); // SyntaxError: Illegal break statement
```

```js
block1: {
  console.log("1");
  (() => {
    break block1; // SyntaxError: Undefined label 'block1'
  })();
}
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-break-statement |

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

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

関連情報
----

* `continue`
* ラベル
* `switch`


function* 宣言 - JavaScript

function\* 宣言
=============

**`function*`** 宣言（`function` キーワードにアスタリスクが付いたもの）は、 `Generator` オブジェクトを返すジェネレーター関数を定義します。

ジェネレーター関数は `GeneratorFunction` コンストラクターや、関数式の構文を使用して定義することもできます。

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

構文
--

```js
function\* name(param0) {
  statements
}
function\* name(param0, param1) {
  statements
}
function\* name(param0, param1, /\* … ,\*/ paramN) {
  statements
}
```

**メモ:** ジェネレーター関数には、対応するアロー関数はありません。

### 引数

`name`

関数名。

`param` 省略可

関数の形式上の引数の名前。

`statements`

関数の本体を構成する文。

解説
--

ジェネレーターは処理を抜け出したり、後から復帰したりすることができる関数です。ジェネレーターのコンテキスト（変数の値）は復帰しても保存されます。

JavaScript のジェネレーターは、特にプロミスと組み合わせることで、非同期プログラミングのための非常に強力なツールとなり、コールバック地獄や制御の逆転などのようなコールバックの問題を、完全に解決できるわけではないものの、軽減することができます。しかし、これらの問題は非同期関数を使用すると、さらにシンプルに解決することができます。

ジェネレーター関数を呼び出しても関数はすぐには実行されません。代わりにその関数のジェネレーターオブジェクトが返されます。イテレーターの `next()` メソッドが呼び出されると、ジェネレーター関数の処理は、イテレーターから返された値を特定する最初の `yield` 演算子か、ほかのジェネレーター関数に委任する `yield*` に達するまで実行されます。`next()` メソッドは産出された値を含む `value` プロパティと、ジェネレーターが最後の値を持つかを真偽値で示す `done` プロパティを持つオブジェクトを返します。引数つきで`next()` を呼び出すと、ジェネレーター関数の実行が再開され、処理が停止していた `yield` 式を `next()` の引数で置き換えます。

 ジェネレーターで `return` 文が実行されると、ジェネレーターが終了します（つまり、それによって返されたオブジェクトの `done` プロパティが `true` に設定されます）。値が返された場合、それはジェネレーターによって返されたオブジェクトの `value` プロパティとして設定されます。 `return` 文とよく似ていますが、ジェネレーターの内部でエラーが発生した場合は、ジェネレーターの本体の中でキャッチしない限り、ジェネレーターは終了します。
 ジェネレーターが終了すると、それ以降の `next()` の呼び出しでは、そのジェネレーターのコードは実行されず、 `{value: undefined, done: true}` の形のオブジェクトが返されるだけです。

`function*` 宣言はスコープの先頭に巻き上げられ、そのスコープのどこからでも呼び出すことができます。

例
-

### 単純な例

```js
function\* idMaker() {
  let index = 0;
  while (true) {
    yield index++;
  }
}

const gen = idMaker();

console.log(gen.next().value); // 0
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // 3
// …
```

### yield\* を使用した例

```js
function\* anotherGenerator(i) {
  yield i + 1;
  yield i + 2;
  yield i + 3;
}

function\* generator(i) {
  yield i;
  yield\* anotherGenerator(i);
  yield i + 10;
}

const gen = generator(10);

console.log(gen.next().value); // 10
console.log(gen.next().value); // 11
console.log(gen.next().value); // 12
console.log(gen.next().value); // 13
console.log(gen.next().value); // 20
```

### ジェネレーターに引数を渡す

```js
function\* logGenerator() {
  console.log(0);
  console.log(1, yield);
  console.log(2, yield);
  console.log(3, yield);
}

const gen = logGenerator();

// 最初の next の呼び出しで、関数の最初から、
// 最初の yield 文の前まで実行される。
gen.next(); // 0
gen.next("pretzel"); // 1 pretzel
gen.next("california"); // 2 california
gen.next("mayonnaise"); // 3 mayonnaise
```

### ジェネレーターにおける return 文

```js
function\* yieldAndReturn() {
  yield "Y";
  return "R";
  yield "unreachable";
}

const gen = yieldAndReturn();
console.log(gen.next()); // { value: "Y", done: false }
console.log(gen.next()); // { value: "R", done: true }
console.log(gen.next()); // { value: undefined, done: true }
```

### オブジェクトプロパティとしてのジェネレーター

```js
const someObj = {
  \*generator() {
    yield "a";
    yield "b";
  },
};

const gen = someObj.generator();

console.log(gen.next()); // { value: 'a', done: false }
console.log(gen.next()); // { value: 'b', done: false }
console.log(gen.next()); // { value: undefined, done: true }
```

### オブジェクトメソッドとしてのジェネレーター

```js
class Foo {
  \*generator() {
    yield 1;
    yield 2;
    yield 3;
  }
}

const f = new Foo();
const gen = f.generator();

console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 3, done: false }
console.log(gen.next()); // { value: undefined, done: true }
```

### 計算プロパティとしてのジェネレーター

```js
class Foo {
  \*[Symbol.iterator]() {
    yield 1;
    yield 2;
  }
}

const SomeObj = {
  \*[Symbol.iterator]() {
    yield "a";
    yield "b";
  },
};

console.log(Array.from(new Foo())); // [ 1, 2 ]
console.log(Array.from(SomeObj)); // [ 'a', 'b' ]
```

### ジェネレーターはコンストラクターではない

```js
function\* f() {}
const obj = new f(); // throws "TypeError: f is not a constructor
```

### 式で定義されたジェネレーター

```js
const foo = function\* () {
  yield 10;
  yield 20;
};

const bar = foo();
console.log(bar.next()); // {value: 10, done: false}
```

### ジェネレーターの例

```js
function\* powers(n) {
  //endless loop to generate
  for (let current = n; ; current \*= n) {
    yield current;
  }
}

for (const power of powers(2)) {
  // controlling generator
  if (power > 32) {
    break;
  }
  console.log(power);
  // 2
  // 4
  // 8
  // 16
  // 32
}
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-generator-function-definitions |

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

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

関連情報
----

* `function* 式`
* `GeneratorFunction` オブジェクト
* 反復処理プロトコル
* `yield`
* `yield*`
* `Function` オブジェクト
* `function` 宣言
* `function` 式
* 関数と関数スコープ
* その他のウェブリソース:
    + Regenerator an ES2015 generator compiler to ES5
    + Forbes Lindesay: Promises and Generators: control flow utopia — JSConf EU 2013
    + Task.js
    + Iterating generators asynchronously


ブロック - JavaScript

ブロック
====

**ブロック文** は 0 個以上の文をグループ化するのに使われます。ブロックは中括弧（「波括弧」）の組で区切られ、0 個以上の文または宣言のリストを含みます。

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

構文
--

```js
{
  StatementList
}
```

`StatementList`

ブロック文の中でグループ化される文や宣言です。

解説
--

ブロック文は、他の言語ではよく**複合文**と呼ばれます。これは複数の文を JavaScript からみて 1 つの文にまとめるために使用します。ブロック内に複数の文をまとめることは、JavaScript では、特に `if...else` and `for` などのフロー制御文との関連で良く行われることです。反対の動作は空文を使用することで実現でき、これは 1 つの文が必要な場所に文を置かずにおくことができます。

さらに、`let`、`const`、`class` などのブロックスコープ宣言と組み合わせることで、IIFE のように、一時変数がグローバル名前空間を汚染するのを防ぐことができます。

### 非厳格モード時の var または関数定義のブロックスコープの規則

非厳格モードでは、`var` の宣言や、関数宣言で作成された変数は、ブロックスコープを**持ちません**。ブロック内で導入された変数は、それを含んでいる関数またはスクリプトがスコープとなり、変数を設定した効果は、そのブロック自体を超えて持続します。言い換えれば、ブロック文はスコープを作成しません。例えば、

```js
var x = 1;
{
  var x = 2;
}
console.log(x); // 2
```

これが 2 を出力するのは、ブロックの中の `var x` 文がブロックより前と同じスコープを持つからです。

非厳格モードでは、ブロック内の関数定義は奇妙な動きをします。使用しないでください。

### 厳格モード時の let、const、関数宣言のブロックスコープの規則

対照的に、`let`、`const`、`class` で宣言された識別子は、ブロックスコープを持ちます。

```js
let x = 1;
{
  let x = 2;
}
console.log(x); // 1
```

この `x = 2` は、それが定義されたブロックのスコープに制限されています。

同じことが `const` にも言えます。

```js
const c = 1;
{
  const c = 2;
}
console.log(c); // 1 が出力され、SyntaxError は発生しない...
```

ブロックスコープを持つ `const c = 2` は、ブロック内で固有に宣言することができるため、`SyntaxError: Identifier 'c' has already been declared` を発生させ*ない*ことに注意してください。

厳格モードでは、ブロック内の関数宣言はそのブロックのスコープを持ち、巻き上げられます。

```js
"use strict";

{
  foo(); // "foo" と出力
  function foo() {
    console.log("foo");
  }
}

foo(); // ReferenceError: foo is not defined
```

例
-

### for ループの本体としてブロック文を使用する

`for` ループは本体として単一の文を受け入れます。

```js
for (let i = 0; i < 10; i++) console.log(i);
```

ループ本体で複数の文を使用したい場合は、1 つのブロック文にまとめることができます。

```js
for (let i = 0; i < 10; i++) {
  console.log(i);
  console.log(i \*\* 2);
}
```

### ブロック文を使用したデータのカプセル化

`let` と `const` の宣言は、それを含むブロックのスコープになります。これにより、データを関数で包むことなく、グローバルスコープから隠すことができます。

```js
let sector;
{
  // これらの変数はこのブロックのスコープであり、
  // ブロックの後でアクセスすることはできません。
  const angle = Math.PI / 3;
  const radius = 10;
  sector = {
    radius,
    angle,
    area: (angle / 2) \* radius \*\* 2,
    perimeter: 2 \* radius + angle \* radius,
  };
}
console.log(sector);
// {
// radius: 10,
// angle: 1.0471975511965976,
// area: 52.35987755982988,
// perimeter: 30.471975511965976
// }
console.log(typeof radius); // "undefined"
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-block |

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

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

関連情報
----

* `while`
* `if...else`
* `let`


switch - JavaScript

switch
======

**`switch`** 文は式を評価して、一連の `case` 節に対してその式の値を照合し、最初に値が一致した `case` 節の後の文を、`break` 文に出会うまで実行します。一致した `case` の後にある文も同様に実行します。`switch` 文の `default` 節には、 `case` が式の値と一致しない場合にジャンプします。

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

構文
--

```js
switch (expression) {
  case value1:
    文
  case value2:
    文
  // …
  case valueN:
    文
  default:
    文
}
```

`expression`

結果が各 `case` 節と一致するか調べる式。

`case valueN` 省略可

`expression` との照合に使用される `case` 節です。`expression` が指定された `valueN` （任意の式）と一致した場合、 `case` 節の直後の文から、 `switch` 文の終わりか、最初に遭遇する `break` のいずれかに達するまで実行されます。

`default` 省略可

`default` 節。 `expression` の値がいずれの `case` 節とも一致しない場合、この節が実行されます。 `switch` 文に存在できる `default` 節は 1 つだけです。

解説
--

`switch` 文はまず始めに式を評価します。次に、式が入力式の結果と評価される値が等しい最初の `case` 節を（厳密等価演算子を使用して）探し、その節の後の文をすべて実行します。

節の値は必要なときにしか評価されません。一致する `case` 節がすでに見つかっている場合、以降の `case` 節の値は評価されません。これは、落下が発生した場合にも同様です。

```js
switch (undefined) {
  case console.log(1):
  case console.log(2):
}
// 1 だけが出力されます
```

一致する `case` 節が見つからない場合、プログラムは省略可能な `default` 節を探し、見つかればその節に制御を移し、関連する文を実行します。`default` 節が見つからない場合、プログラムは `switch` の終了に続く文で実行を続けます。慣習では、`default` 節は最後の節ですが、そうである必要はありません。`switch` 文は `default` 節を一つだけ持つことができます。複数の `default` 節がある場合は `SyntaxError` が発生します。

### 中断と落下

`switch` 文の本体の中で `break` 文を使用すると、2 つの `case` 節の間のすべての文が実行されたとき、早期に抜け出すことができます。実行は `switch` に続く最初の文で継続されます。

もし `break` が省略された場合は、次の `case` 節に進みます。たとえ `default` 節であっても、その値が一致するかどうかに関係なく、実行は続行されます。この動作は「落下」 (fall-through) と呼ばれます。

```js
const foo = 0;
switch (foo) {
  case -1:
    console.log("negative 1");
    break;
  case 0: // foo の値はこの式に一致します。実行はここから始まります。
    console.log(0);
  // break を忘れています。実行は落下します。
  case 1: // 'case 0:' に break 文がないので、同様に実行されます。
    console.log(1);
    break; // break に出会いました。 'case 2:' へは続きません。
  case 2:
    console.log(2);
    break;
  default:
    console.log("default");
}
// 0 と 1 が出力される
```

適切なコンテキストにおいて、その他の制御フロー文は `switch` 文から抜け出す効果があります。例えば、`switch`文が関数の中に含まれている場合、`return` 文は関数本体の実行を終了し、したがって `switch` 文の実行を終了させます。もし `switch` 文がループに含まれている場合、`continue` 文は `switch` 文を中断し、ループの次の反復処理にジャンプさせます。

### 字句スコープ

`case` と `default` 句はラベルのようなものです。これらは、制御フローがジャンプする可能性のある場所があることを示します。しかし、これらは字句のスコープそのものを作成するわけではありません（自動的に脱出することもありません。上で示したとおりです）。例えば次のようになります。

```js
const action = "say\_hello";
switch (action) {
  case "say\_hello":
    const message = "hello";
    console.log(message);
    break;
  case "say\_hi":
    const message = "hi";
    console.log(message);
    break;
  default:
    console.log("Empty action received.");
}
```

この例では、 "Uncaught SyntaxError: Identifier 'message' has already been declared" というエラーが出力されます。なぜなら、最初の `const message = 'hello';` と 2 つ目の `const message = 'hi';` の宣言が、自分自身で別個の case 節の中にあっても、競合してしまうからです。結局のところ、これは両方の `const` 宣言が `switch` 本体で作成された同じブロックスコープ内にあることが原因です。

これを修正するには、 `case` 節の中で `let` や `const` 宣言を使用する必要がある場合には、それをブロックで囲みます。

```js
const action = "say\_hello";
switch (action) {
  case "say\_hello": {
    const message = "hello";
    console.log(message);
    break;
  }
  case "say\_hi": {
    const message = "hi";
    console.log(message);
    break;
  }
  default: {
    console.log("Empty action received.");
  }
}
```

これで、このコードはエラーもなく、本来のように `hello` をコンソールに出力するようになります。

例
-

### switch の使用

次の例では、 `expr` が `Bananas` と評価された場合、プログラムは `case 'Bananas'` で値に一致し、関連付けられた文を実行します。 `break` と遭遇したとき、プログラムは `switch` から抜け出し、 `switch` に続く文を実行します。 `break` が省略された場合は、 `case 'Cherries'` に対する文も実行されます。

```js
switch (expr) {
  case "Oranges":
    console.log("Oranges are $0.59 a pound.");
    break;
  case "Apples":
    console.log("Apples are $0.32 a pound.");
    break;
  case "Bananas":
    console.log("Bananas are $0.48 a pound.");
    break;
  case "Cherries":
    console.log("Cherries are $3.00 a pound.");
    break;
  case "Mangoes":
  case "Papayas":
    console.log("Mangoes and papayas are $2.79 a pound.");
    break;
  default:
    console.log(`Sorry, we are out of ${expr}.`);
}

console.log("Is there anything else you'd like?");
```

### case の間に default を置いた場合

もし一致するものが見つからなければ、 `default` 節から実行が始まり、それ以降のすべての文が実行されます。

```js
const foo = 5;
switch (foo) {
  case 2:
    console.log(2);
    break; // この break に当たれば 'default:' に継続されることはない
  default:
    console.log("default");
  // 落下
  case 1:
    console.log("1");
}
```

他のすべての `case` の前に `default` を設定した場合にも機能します。

### 落下の活用

この方法は、 `case` 節の配下に `break` がない場合に、次の `case` も基準を満たすかに関係なく実行されるという事実を活用します。

これは連続した `case` 文でひとつの操作を行う例であり、4 つの異なる値でまったく同じ操作を行います。

```js
const Animal = "Giraffe";
switch (Animal) {
  case "Cow":
  case "Giraffe":
  case "Dog":
  case "Pig":
    console.log("This animal is not extinct.");
    break;
  case "Dinosaur":
  default:
    console.log("This animal is extinct.");
}
```

次のものは一連の `case` 節と複数の操作の例であり、与えられた整数によって、異なる出力を行います。これは、 `case` 節を置いた順番に走査することを示しており、数値的な順序である必要はありません。 JavaScript では、この `case` 文の中に文字列の定義も混ぜることができます。

```js
const foo = 1;
let output = "Output: ";
switch (foo) {
  case 0:
    output += "So ";
  case 1:
    output += "What ";
    output += "Is ";
  case 2:
    output += "Your ";
  case 3:
    output += "Name";
  case 4:
    output += "?";
    console.log(output);
    break;
  case 5:
    output += "!";
    console.log(output);
    break;
  default:
    console.log("Please pick a number from 0 to 5!");
}
```

この例の出力は以下のとおりです。

| 値 | 出力するテキスト |
| --- | --- |
| `foo` が `NaN` であるか、 `1`, `2`, `3`, `4`, `5`, `0` のどれでもない | Please pick a number from 0 to 5! |
| `0` | Output: So What Is Your Name? |
| `1` | Output: What Is Your Name? |
| `2` | Output: Your Name? |
| `3` | Output: Name? |
| `4` | Output: ? |
| `5` | Output: ! |

### if...else チェーンによる代替

`if...else` という照合を何度もすることになることが多いのではないでしょうか。

```js
if ("fetch" in globalThis) {
  // fetch でリソースを読み取る
} else if ("XMLHttpRequest" in globalThis) {
  // XMLHttpRequest でリソースを読み取る
} else {
  // 何らかのカスタム AJAX ロジックでリソースを読み取る
}
```

このパターンは、一連の `===` 比較を行うものではありませんが、 `switch` 構造に変換することができます。

```js
switch (true) {
  case "fetch" in globalThis:
    // fetch でリソースを読み取る
    break;
  case "XMLHttpRequest" in globalThis:
    // XMLHttpRequest でリソースを読み取る
    break;
  default:
    // 何らかのカスタム AJAX ロジックでリソースを読み取る
    break;
}
```

`if...else` の代わりに `switch (true)` パターンを使用すると、落下動作を使用する場合に特に有益です。

```js
switch (true) {
  case isSquare(shape):
    console.log("This shape is a square.");
  // square は rectangle でもあるため、落下する
  case isRectangle(shape):
    console.log("This shape is a rectangle.");
  case isQuadrilateral(shape):
    console.log("This shape is a quadrilateral.");
    break;
  case isCircle(shape):
    console.log("This shape is a circle.");
    break;
}
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-switch-statement |

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

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

関連情報
----

* `if...else`


try...catch - JavaScript

try...catch
===========

**`try...catch`** 文は `try` ブロックと、`catch` ブロックか `finally` ブロックか、その両方から構成されます。まず `try` ブロック内のコードが実行され、そこで例外が発生すると、`catch` ブロック内のコードが実行されます。`finally` ブロック内のコードは、制御する流れが構造全体を抜ける前に、常に実行されます。

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

構文
--

```js
try {
  tryStatements
} catch (exceptionVar) {
  catchStatements
} finally {
  finallyStatements
}
```

`tryStatements`

実行される文です。

`catchStatements`

`try` ブロックの中で例外が発生した場合に実行される文です。

`exceptionVar` 省略可

関連する `catch` ブロックが捕捉した例外を保持するためのオプションの識別子です。もし `catch` ブロックが例外の値を利用しない場合は、 `exceptionVar` とその周りの括弧を省略して `catch {...}` のようにすることができます。

`finallyStatements`

`try...catch...finally` 構造から制御フローが脱出する前に実行される文です。これらの文は、例外が発生されたり捕捉されたりしたかどうかに関係なく実行されます。

解説
--

`try` 文は、常に `try` ブロックから始まります。それから、`catch` ブロックまたは `finally` ブロックが存在する必要があります。`catch` および `finally` ブロックが両方存在しても構いません。すなわち、`try` 文には 3 つの形態があります。

* `try...catch`
* `try...finally`
* `try...catch...finally`

`if` や `for` などの他の構造とは異なり、`try`、`catch`、`finally` の各ブロックは単一の文ではなく、ブロックでなければなりません。

```js
try doSomething(); // SyntaxError
catch (e) console.log(e);
```

`catch` ブロックは、例外が `try` ブロックの中で発生した場合に何をするかを指定する文を含みます。`try` ブロック内（または `try` ブロック内から呼び出された関数の中）のいずれかの文で例外が発生した場合は、制御は即座に `catch` ブロックへ移ります。`try` ブロックの中で例外が発生しなかった場合は、`catch` ブロックは飛ばされます。

`finally` ブロックは、制御フローが `try...catch...finally` 構造から脱出する前に常に実行されます。これは常に実行され、例外が発生したかどうか、捕捉されたかどうかには関係ありません。

1 つ以上の `try` 文を入れ子にする事ができます。内側の `try` 文が `catch` ブロックを持っていない場合、それを囲んでいる `try` 文の `catch` ブロックに入ります。

`try` を使用して JavaScript の例外を処理することもできます。 JavaScript の例外に関する情報は JavaScript ガイドを参照してください。

### 無条件の catch ブロック

`catch` ブロックが使われている場合、`try` ブロックの中から任意の例外が発生すると、`catch` ブロックが実行されます。例えば、以下のコードで例外が発生すると、制御は `catch` ブロックへ移動します。

```js
try {
  throw "myException"; // 例外を生成
} catch (e) {
  // 任意の例外を操作するための文
  logMyErrors(e); // エラーハンドラーに例外オブジェクトを渡します
}
```

`catch` ブロックは例外の値を保持する識別子（上記の例では `e`）を指定します。この値は `catch` ブロックのスコープ内でのみ利用できます。

### 条件付き catch ブロック

「条件付き `catch` ブロック」は、下記のように `try...catch` ブロックを `if...else if...else` 構造と組み合わせることで作成することができます。

```js
try {
  myroutine(); // 3 つの例外が発生する可能性があります
} catch (e) {
  if (e instanceof TypeError) {
    // TypeError 例外を処理するための文
  } else if (e instanceof RangeError) {
    // RangeError 例外を処理するための文
  } else if (e instanceof EvalError) {
    // EvalError 例外を処理するための文
  } else {
    // 任意の指定されていない例外を操作するための文
    logMyErrors(e); // エラーハンドラーに例外オブジェクトを渡す
  }
}
```

よくある使用例としては、次のように想定済みの一部のエラーのみを捕捉（および無視）し、それ以外の場合はエラーを送出し直す場合です。

```js
try {
  myRoutine();
} catch (e) {
  if (e instanceof RangeError) {
    // 頻発する想定済みのエラーを処理する文
  } else {
    throw e; // エラーを変更しないまま送出し直す
  }
}
```

### 例外識別子

例外が `try` ブロックの中で発生したときは、`exceptionVar`（たとえば、`catch (e)` における `e`）が例外の値を保持します。この識別子を使用して、発生した例外についての情報を取得することができます。この識別子は `catch` ブロックのスコープでのみ利用できます。例外の値が必要ない場合にはこれは省略できます。

```js
function isValidJSON(text) {
  try {
    JSON.parse(text);
    return true;
  } catch {
    return false;
  }
}
```

### finally ブロック

`finally` ブロックには、`try` ブロックおよび `catch` ブロックを実行した後で、`try...catch...finally` の次の文が実行される前に実行される文が入ります。制御フローは以下のいずれかの場面で、常に `finally` ブロックに入ります。

* `try` ブロックが正常に（例外が発生せずに）終了する直前
* `catch` ブロックの実行が正常に終了する直前
* 制御フロー文（`return`、`throw`、`break`、`continue`）が `try` ブロックや `catch` ブロックの中で実行される直前

なお、`finally` ブロックは例外が発生するかどうかにかかわらず実行されます。また、例外が発生した場合、`finally` ブロックは例外を処理する `catch` ブロックがなくても実行されます。

次の例では `finally` ブロックの一つの使用例を示します。このコードはファイルを開き、それからファイルを使用する分を実行します。`finally` ブロックは、例外が発生したとしてもその後で確実にファイルを閉じるよう保証します。

```js
openMyFile();
try {
  // リソースを結び付けます
  writeMyFile(theData);
} finally {
  closeMyFile(); // リソースを常に閉じます
}
```

制御フロー文（`return`, `throw`, `break`, `continue`）を `finally` ブロック内で使うと、`try` ブロックや `catch` ブロックの完了値を「マスク」します。この例では、`try` ブロックは 1 を返そうとしますが、返す前にまず `finally` ブロックに制御を委ねるので、代わりに `finally` ブロックの返値が返されます。

```js
function doIt() {
  try {
    return 1;
  } finally {
    return 2;
  }
}

doIt(); // returns 2
```

一般に、`finally` ブロックの中に制御フロー文を置くのは悪い考えです。クリーンアップのためのコードのみを使用してください。

例
-

### 入れ子になった try ブロック

最初に、次のもので何が起きるか見てみましょう。

```js
try {
  try {
    throw new Error("oops");
  } finally {
    console.log("finally");
  }
} catch (ex) {
  console.error("outer", ex.message);
}

// ログ:
// "finally"
// "outer" "oops"
```

ここで、既に内部の `try` ブロックに `catch` ブロックを追加しているので、既に例外を捕捉しています。

```js
try {
  try {
    throw new Error("oops");
  } catch (ex) {
    console.error("inner", ex.message);
  } finally {
    console.log("finally");
  }
} catch (ex) {
  console.error("outer", ex.message);
}

// ログ:
// "inner" "oops"
// "finally"
```

そして、エラーを送りなおします。

```js
try {
  try {
    throw new Error("oops");
  } catch (ex) {
    console.error("inner", ex.message);
    throw ex;
  } finally {
    console.log("finally");
  }
} catch (ex) {
  console.error("outer", ex.message);
}

// ログ:
// "inner" "oops"
// "finally"
// "outer" "oops"
```

送り直されない限り、例外はどれでも最も内側の `catch` ブロックで一度だけ捕捉されます。もちろん、何らかの例外が「内側の」のブロックで発生した場合（`catch` ブロックのコードで例外が発生することを行った場合）、「外側の」ブロックで捕捉されます。

### finally ブロックからの return

`finally` ブロックが値を返した場合、 `try` ブロックや `catch` ブロックの `return` 文に関係なく、その値が `try-catch-finally` 全体の返値になります。
 これは `catch` ブロック内で例外が発生した場合も含まれます。

```js
(() => {
  try {
    try {
      throw new Error("oops");
    } catch (ex) {
      console.error("inner", ex.message);
      throw ex;
    } finally {
      console.log("finally");
      return;
    }
  } catch (ex) {
    console.error("outer", ex.message);
  }
})();

// ログ:
// "inner" "oops"
// "finally"
```

外側の "oops" は `finally` ブロックに return があるため送出されません。同じことが、`catch` ブロックから返されているその他の値にも適用されます。

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-try-statement |

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

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

関連情報
----

* `Error`
* `throw`


with - JavaScript

with
====

**非推奨:** この機能は非推奨になりました。まだ対応しているブラウザーがあるかもしれませんが、すでに関連するウェブ標準から削除されているか、削除の手続き中であるか、互換性のためだけに残されている可能性があります。使用を避け、できれば既存のコードは更新してください。このページの下部にある互換性一覧表を見て判断してください。この機能は突然動作しなくなる可能性があることに注意してください。

**メモ:** `with` 文の使用は推奨されません。混乱を招くバグや互換性問題の原因となる可能性があり、最適化ができなくなり、厳格モードでは禁止されているからです。推奨される代替案は、プロパティをアクセスしたいオブジェクトを一時変数に割り当てることです。

**`with`** 文は、文に対するスコープチェーンを拡張します。

構文
--

```js
with (expression)
  statement
```

`expression`

文を評価するときに使われるスコープチェーンに、与えられたオブジェクトを追加します。オブジェクトの周りの括弧は必須です。

`statement`

任意の文。複数の文を実行するためには、それらの文をグループ化するためにブロック文（`{ ... }`）を使ってください。

解説
--

識別子には、修飾識別子と非修飾識別子の 2 種類があります。非修飾識別子は、どこから来たのかを示さないものです。

```js
foo; // 非修飾識別子
foo.bar; // bar は修飾識別子
```

通常、非修飾識別子は、その名前を持つ変数をスコープチェーンで検索することで解決し、修飾識別子は、その名前を持つプロパティをオブジェクトのプロトタイプチェーンで検索することで解決します。

```js
const foo = { bar: 1 };
console.log(foo.bar);
// foo は変数としてスコープチェーン内で見つかる。
// bar は foo の中でプロパティとして見つかる。
```

例外として、グローバルオブジェクトは、スコープチェーンの最上位に位置し、そのプロパティは自動的にグローバル変数になり、修飾子なしで参照することができます。

```js
console.log(globalThis.Math === Math); // true
```

`with` 文は、その文本体の評価の間、このスコープチェーンの先頭に、与えられたオブジェクトを追加します。すべての非修飾名は、上位スコープチェーンで検索される前に、まずオブジェクト内で（`in` チェックを介して）検索されます。

非修飾参照がオブジェクトのメソッドを参照した場合、そのメソッドはそのオブジェクトを `this` 値として呼び出されることに注意してください。

```js
with ([1, 2, 3]) {
  console.log(toString()); // 1,2,3
}
```

オブジェクトは `@@unscopables` プロパティを持つことができますが、これはスコープチェーンに（後方互換性のために）追加してはならないプロパティのリストを定義するものです。詳細は `Symbol.unscopables` のドキュメントを参照してください。

`with` 文を使用する理由は、一時変数を 1 つ節約するためと、長いオブジェクト参照を繰り返すことを避けるためにファイルサイズを縮小するためです。しかし、`with` 文が好ましくない理由はもっとたくさんあります。

* パフォーマンス: `with` 文は、すべての名前検索において、指定したオブジェクトを最初に検索することを強制します。したがって、指定したオブジェクトのメンバーでない識別子はすべて、`with` ブロックの中で見つかるのがより遅くなります。さらに、オプティマイザーはそれぞれの非修飾識別子が何を参照しているのかについて仮定することができないため、識別子を使用するたびに同じプロパティの検索を繰り返さなければなりません。
* 可読性: `with` 文により、人間の読み手や JavaScript コンパイラーにとって、修飾されていない名前がスコープチェーンで見つかるかどうか、見つかるとしたらどのオブジェクトで見つけられるかを判断するのを難しくなります。以下の例を見てください。

```js
function f(x, o) {
  with (o) {
    console.log(x);
  }
}
```

`f` の定義だけを見ていると、`with`本体の`x`が何を参照しているのかがわかりません。`f` が呼び出されて初めて、`x` が `o.x` であるか、`f` の最初の形式引数であるかを判断することができます。もし、2 つ目の引数として渡すオブジェクトで `x` を定義し忘れても、エラーは発生しませんが、その代わりに予期せぬ結果が発生します。また、このようなコードが実際にどのような意図を持っているのかも不明です。
* 前方互換性: `with` を使用したコードは、前方互換性がない可能性があります。特に、将来的に複数のプロパティを持つようになるかもしれない、プレーンオブジェクト以外で使用する場合です。次のような例を考えてみましょう。

```js
function f(foo, values) {
  with (foo) {
    console.log(values);
  }
}
```

ECMAScript 5 環境で `f([1, 2, 3], obj)` を呼び出すと、`with` 文の中にある `values` の参照先は `obj` に解決されます。ところが、ECMAScript 2015 では `values` プロパティが `Array.prototype` に導入されました (よって、すべての配列で使用できます)。従って、環境を更新すると、`with` 文の内部にある `values` の参照先は `[1, 2, 3].values` に解決されるようになり、バグを引き起こす可能性があります。
 この具体的な例では、`values` は `Array.prototype[@@unscopables]` によってスコープ不可と定義されているので、やはり `values` 引数に正しく解決さ れます。もし、スコープ不可と定義されていなければ、デバッグが困難な課題になるのは目に見えています。
例
-

### with の使用

次の `with` 文は、`Math` オブジェクトが既定のオブジェクトであると指定しています。`with` 文内の複数の文は、オブジェクトを指定することなく、 `PI` プロパティ、 `cos` メソッド、および `sin` メソッドを参照しています。JavaScript は、これらの参照に対して `Math` オブジェクトを仮定します。

```js
let a, x, y;
const r = 10;

with (Math) {
  a = PI \* r \* r;
  x = r \* cos(PI);
  y = r \* sin(PI / 2);
}
```

### プロパティを現在のスコープに分割代入して with 文を避ける

通常、プロパティの分割代入によって `with` を使用するのを避けることができます。ここでは、`with` が余分なスコープを作る動作を模倣するために余分なブロックを作成していますが、実際の使用では、通常はこのブロックを除外することができます。

```js
let a, x, y;
const r = 10;

{
  const { PI, cos, sin } = Math;
  a = PI \* r \* r;
  x = r \* cos(PI);
  y = r \* sin(PI / 2);
}
```

### IIFE を使用して with 文を避ける

長い名前の参照を何度も再利用しなければならない式を作成する場合、式の中でその長い名前を排除することが目的であれば、式を IIFE で囲み、長い名前を引数として提供することができます。

```js
const objectHavingAnEspeciallyLengthyName = { foo: true, bar: false };

if (((o) => o.foo && !o.bar)(objectHavingAnEspeciallyLengthyName)) {
  // This branch runs.
}
```

### with 文とプロキシーを使用して動的な名前空間を生成

`with` はすべての変数の探索をプロパティの探索に変換し、Proxy ではすべてのプロパティの探索の呼び出しをトラップすることができます。これらを組み合わせることで、動的な名前空間を作成することができます。

```js
const namespace = new Proxy(
  {},
  {
    has(target, key) {
      // `console` のようなグローバルプロパティはトラップしない
      if (key in globalThis) {
        return false;
      }
      // すべてのプロパティの参照をトラップ
      return true;
    },
    get(target, key) {
      return key;
    },
  },
);

with (namespace) {
  console.log(a, b, c); // "a" "b" "c"
}
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-with-statement |

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

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

関連情報
----

* block
* 厳格モード
* `Symbol.unscopables`
* `Array.prototype[@@unscopables]`


debugger - JavaScript

debugger
========

**`debugger`** 文は、ブレークポイントの設定などの任意の利用可能なデバッグ機能を呼び出します。デバッグ機能が利用可能ではない場合、この文は効果がありません。

構文
--

```js
debugger;
```

例
-

### debugger 文の使用

次の例は、関数が呼び出されたときに、デバッガーを（存在すれば）呼び出すように、 `debugger` 文が挿入されているコードを示します。

```js
function potentiallyBuggyCode() {
  debugger;
  // do potentially buggy stuff to examine, step through, etc.
}
```

デバッガーが起動していると、実行は `debugger` 文で停止します。スクリプトのソース内でのブレークポイントと似ています。

![開発者ツールをブラウザーに開き、デバッガーパネルで、変数、スコープ、イベントなどを詳しく調べるために、デバッガー文で実行を一時停止している様子。](/ja/docs/Web/JavaScript/Reference/Statements/debugger/screen_shot_2014-02-07_at_9.14.35_am.png)

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-debugger-statement |

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

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

関連情報
----

* Firefox 開発者ツール内のデバッガー （英語）