Promise.all() - JavaScript

Promise.all()
=============

**`Promise.all()`** は静的メソッドで、入力としてプロミスの集合の反復可能オブジェクトを取り、単一の `Promise` を返します。この返却されたプロミスは、入力されたプロミスがすべて履行されたとき（空のイテレーターが渡されたときを含む）、その履行された値の配列で、履行されます。入力されたプロミスのいずれかが拒否されると、その最初の拒否理由とともに拒否されます。

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

構文
--

```js
Promise.all(iterable)
```

### 引数

`iterable`

反復可能オブジェクト（プロミスの配列 (`Array`) など）。

### 返値

次のような `Promise` です。

* *反復可能*オブジェクトが空であった場合は、**履行済み**になります。
* 渡された*反復可能*オブジェクトのすべてのプロミスが履行されたとき、**非同期に履行されます**。履行された値は、完了順に関係なく、渡されたプロミスの順番で、履行された値の配列となります。渡された*反復可能*オブジェクトが空ではないが、待機中のプロミスがなかった場合、返されたプロミスは（同期的ではなく）非同期的に履行されることに変わりはありません。
* 渡された*反復可能*オブジェクトのいずれかが拒否された場合は、**非同期に拒否されます**。拒否理由は、最初に拒否されたプロミスの拒否理由になります。
解説
--

`Promise.all()` メソッドは、プロミスの並行処理メソッドのうちの一つです。このメソッドは、複数のプロミスの結果を集約するのに便利です。このメソッドは、コード全体が正常に動作するために依存している複数の関連する非同期タスクがあり、コードの実行を続ける前にそれらすべてを履行させたい場合によく使われます。

**メモ:** 日本語の技術文書では、このメソッドが複数のプロミスを並列に処理すると説明されることがありますが、実際には複数のスレッドでプロミスが処理されるわけではないことに注意してください。詳細はプロミスの並行処理を参照してください。

`Promise.all()` は、入力されたプロミスの**いずれか**が拒否されると直ちに拒否されます。それに対して、`Promise.allSettled()` が返すプロミスは、入力されたプロミスのいずれかが拒否されたかどうかに関わらず、すべての入力されたプロミスが完了するのを待ちます。入力された反復可能オブジェクトに含まれるプロミスのすべての最終結果が必要な場合は、`allSettled()` を使用してください。

例
-

### Promise.all() の使用

`Promise.all` はすべての履行（または最初の拒否）を待ちます。

```js
const p1 = Promise.resolve(3);
const p2 = 1337;
const p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("foo");
  }, 100);
});

Promise.all([p1, p2, p3]).then((values) => {
  console.log(values); // [3, 1337, "foo"]
});
```

*反復可能*オブジェクトにプロミスではない値が含まれる場合は無視されますが、（プロミスが履行された場合）返されるプロミスの配列の値にはカウントされます。

```js
// すべての値がプロミスでないため、返されたプロミスは履行される
const p = Promise.all([1, 2, 3]);
// 唯一の入力プロミスはすでに履行されているたので、
// 返されたプロミスは履行される
const p2 = Promise.all([1, 2, 3, Promise.resolve(444)]);
// 1 つの（そして唯一の）入力プロミスが拒否される。
// したがって、返されたプロミスも拒否される。
const p3 = Promise.all([1, 2, 3, Promise.reject(555)]);

// setTimeout を使うことで、キューが空になってからコードを実行することができる
setTimeout(() => {
  console.log(p);
  console.log(p2);
  console.log(p3);
});

// ログ出力
// Promise { <state>: "fulfilled", <value>: Array[3] }
// Promise { <state>: "fulfilled", <value>: Array[4] }
// Promise { <state>: "rejected", <reason>: 555 }
```

### Promise.all の非同期性・同期性

以下の例では `Promise.all` の非同期性（または渡された*反復可能*オブジェクトが空の場合、同期性）を実演します。

```js
// Promise.all をできるだけ早く使用するために、
// すでに解決されたプロミスの配列を渡す
const resolvedPromisesArray = [Promise.resolve(33), Promise.resolve(44)];

const p = Promise.all(resolvedPromisesArray);
// p の値を直接ログ出力
console.log(p);

// setTimeout を使用してスタックが空になった後にコードを実行することができる
setTimeout(() => {
  console.log("キューが空になりました");
  console.log(p);
});

// Logs, in order:
// Promise { <state>: "pending" }
// キューが空になりました
// Promise { <state>: "fulfilled", <value>: Array[2] }
```

`Promise.all` が拒否されたときも同じことが起きます。

```js
const mixedPromisesArray = [Promise.resolve(33), Promise.reject(44)];
const p = Promise.all(mixedPromisesArray);
console.log(p);
setTimeout(() => {
  console.log("キューが空になりました");
  console.log(p);
});

// ログ出力
// Promise { <state>: "pending" }
// キューが空になりました
// Promise { <state>: "rejected", <reason>: 44 }
```

しかし、`Promise.all` は渡された*反復可能*オブジェクトが空の場合だけ同期的に解決します。

```js
const p = Promise.all([]); // 直ちに解決される
const p2 = Promise.all([1337, "hi"]); // プロミスではない値は無視されるが、評価は非同期に行われる
console.log(p);
console.log(p2);
setTimeout(() => {
  console.log("キューが空になりました");
  console.log(p2);
});

// ログ出力:
// Promise { <state>: "fulfilled", <value>: Array[0] }
// Promise { <state>: "pending" }
// キューが空になりました
// Promise { <state>: "fulfilled", <value>: Array[2] }
```

### Promise.all() と非同期関数の使用

非同期関数内では、コードを「過剰に待つ」ことはとてもよくあることです。例えば、以下のような関数が指定されたとします。

```js
function promptForDishChoice() {
  return new Promise((resolve, reject) => {
    const dialog = document.createElement("dialog");
    dialog.innerHTML = `
<form method="dialog">
 <p>What would you like to eat?</p>
 <select>
 <option value="pizza">Pizza</option>
 <option value="pasta">Pasta</option>
 <option value="salad">Salad</option>
 </select>
 <menu>
 <li><button value="cancel">Cancel</button></li>
 <li><button type="submit" value="ok">OK</button></li>
 </menu>
</form>
 `;
    dialog.addEventListener("close", () => {
      if (dialog.returnValue === "ok") {
        resolve(dialog.querySelector("select").value);
      } else {
        reject(new Error("User cancelled dialog"));
      }
    });
    document.body.appendChild(dialog);
    dialog.showModal();
  });
}

async function fetchPrices() {
  const response = await fetch("/prices");
  return await response.json();
}
```

次のように関数を書くかもしれません。

```js
async function getPrice() {
  const choice = await promptForDishChoice();
  const prices = await fetchPrices();
  return prices[choice];
}
```

ただし、`promptForChoice` と `fetchPrices` の実行は、互いの結果には依存しないことに注意してください。ユーザーが料理を選んでいる間、バックグラウンドで価格が取得されても問題ありませんが、上記のコードでは `await` 演算子によって選択が行われるまで非同期関数が一時停止し、その後価格が取得されるまで再度一時停止します。`Promise.all` を使用すれば、結果が指定される前にユーザーが価格の取得を待たずに、これらを並行して実行することができます。

```js
async function getPrice() {
  const [choice, prices] = await Promise.all([
    promptForDishChoice(),
    fetchPrices(),
  ]);
  return prices[choice];
}
```

`Promise.all` はエラー処理が直感的であるため、ここでの並行処理メソッドには最適な選択です。もしいずれかのプロミスが拒否されたら、結果がもう利用できなくなり、 await 式全体が例外を発生します。

`Promise.all` はプロミスの反復可能オブジェクトを受け入れるので、いくつかの非同期関数の実行を並列化するために使用するには、非同期関数を呼び出して返されたプロミスを使用する必要があります。関数はプロミスではないので、 `Promise.all` に直接渡しても動作しません。

```js
async function getPrice() {
  const [choice, prices] = await Promise.all([
    promptForDishChoice,
    fetchPrices,
  ]);
  // `choice` および `prices` は元と同じ非同期関数です。
  // Promise.all() はプロミスでないものには何もしません。
}
```

### Promise.all のフェイルファストの挙動

`Promise.all` は要素のひとつでも拒否されると拒否します。例えば、タイムアウト後に 4 つのプロミスが解決しても、 1 つのプロミスが直ちに拒否された場合、 `Promise.all` は直ちに拒否されます。

```js
const p1 = new Promise((resolve, reject) => {
  setTimeout(() => resolve("one"), 1000);
});
const p2 = new Promise((resolve, reject) => {
  setTimeout(() => resolve("two"), 2000);
});
const p3 = new Promise((resolve, reject) => {
  setTimeout(() => resolve("three"), 3000);
});
const p4 = new Promise((resolve, reject) => {
  setTimeout(() => resolve("four"), 4000);
});
const p5 = new Promise((resolve, reject) => {
  reject(new Error("reject"));
});

// .catch の使用
Promise.all([p1, p2, p3, p4, p5])
  .then((values) => {
    console.log(values);
  })
  .catch((error) => {
    console.error(error.message);
  });

// ログ出力:
// "reject"
```

この動作は失敗する可能性を制御することで変更することができます。

```js
const p1 = new Promise((resolve, reject) => {
  setTimeout(() => resolve("p1\_delayed\_resolution"), 1000);
});

const p2 = new Promise((resolve, reject) => {
  reject(new Error("p2\_immediate\_rejection"));
});

Promise.all([p1.catch((error) => error), p2.catch((error) => error)]).then(
  (values) => {
    console.log(values[0]); // "p1\_delayed\_resolution"
    console.error(values[1]); // "Error: p2\_immediate\_rejection"
  },
);
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-promise.all |

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

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

関連情報
----

* `Promise`
* `Promise.allSettled()`
* `Promise.any()`
* `Promise.race()`


Promise.reject() - JavaScript

Promise.reject()
================

**`Promise.reject()`** は静的メソッドで、引数で与えられた理由で拒否された `Promise` オブジェクトを返します。

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

構文
--

```js
Promise.reject(reason)
```

### 引数

`reason`

この `Promise` が拒否された理由です。

### 返値

与えられた理由で拒否された `Promise` です。

解説
--

静的な `Promise.reject` 関数は拒否された `Promise` を返します。デバッグのために捕捉するエラーを選別したい場合は、 `reason` を `instanceof` `Error` にかけると良いでしょう。

`Promise.reject()` は汎用的であり、サブクラス化に対応しています。つまり、 `Promise` のサブクラスで呼び出すことができ、その結果はサブクラスの種類のプロミスになります。これを行うには、サブクラスのコンストラクターは `Promise()` コンストラクターと同じ呼び出し定義を実装する必要があります。これは、 `resolve` と `reject` コールバックを引数として呼び出すことができる単一の `executor` 関数を引数に取ります。 `Promise.reject()` は、本質的に `new Promise((resolve, reject) => reject(reason))` の短縮形です。

`Promise.resolve()` とは異なり、 `Promise.reject()` は `reason` がすでに `Promise` であっても、常に新しい `Promise` オブジェクトで `reason` をラップします。

例
-

### 静的な Promise.reject() メソッドの使用

```js
Promise.reject(new Error("fail")).then(
  () => {
    // not called
  },
  (error) => {
    console.error(error); // Stacktrace
  },
);
```

### プロミスの拒否

`Promise.resolve` とは異なり、 `Promise.reject` メソッドは既存の `Promise` インスタンスを再利用することはありません。常に `reason` を包んだ新しい `Promise` インスタンスを返します。

```js
const p = Promise.resolve(1);
const rejected = Promise.reject(p);
console.log(rejected === p); // false
rejected.catch((v) => {
  console.log(v === p); // true
});
```

### Promise 以外のコンストラクターに対する reject() の呼び出し

`Promise.reject()` は汎用的なメソッドです。これは `Promise()` コンストラクターと同じ呼び出し定義を実装した任意のコンストラクターで呼び出すことができます。例えば、 `console.log` を `reject` として渡すコンストラクターで呼び出すことができます。

```js
class NotPromise {
  constructor(executor) {
    // The "resolve" and "reject" functions behave nothing like the
    // native promise's, but Promise.reject() calls them in the same way.
    executor(
      (value) => console.log("Resolved", value),
      (reason) => console.log("Rejected", reason),
    );
  }
}

Promise.reject.call(NotPromise, "foo"); // Logs "Rejected foo"
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-promise.reject |

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

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

関連情報
----

* `Promise`


Promise.race() - JavaScript

Promise.race()
==============

**`Promise.race()`** は静的メソッドで、入力としてプロミスの反復可能オブジェクトを受け取り、単一の `Promise` を返します。この返されたプロミスは、最初に決定したプロミスの最終的な状態で決定されます。

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

構文
--

```js
Promise.race(iterable)
```

### 引数

`iterable`

反復可能オブジェクト（プロミスの `Array` など）です。

### 返値

`Promise` で、反復可能オブジェクトの最初のプロミスの最終的な状態で**非同期に決定**します。言い換えると、最初に決定されたプロミスが履行されれば履行され、最初に決定されたプロミスが拒否されれば拒否されます．返されるプロミスは、渡された反復可能オブジェクトが空の場合、永久に待機状態になります。渡された反復可能オブジェクトが空ではないが、待機中のプロミスを含んでいなかった場合、返されたプロミスは（同期的ではなく）非同期的に決定されます。

解説
--

`Promise.race()` メソッドはプロミス並行処理メソッドの 1 つです。これは最初の非同期タスクを完全に完了させたいが、最終的な状態は気にしない（つまり、成功も失敗もあり得る）場合に有用です。

**メモ:** 日本語の技術文書では、このメソッドが複数のプロミスを並列に処理すると説明されることがありますが、実際には複数のスレッドでプロミスが処理されるわけではないことに注意してください。詳細はプロミスの並行処理を参照してください。

反復可能オブジェクトに 1 つ以上の非プロミス値および/または既に確定したプロミスが格納されている場合、 `Promise.race()` は反復可能オブジェクトで最初に見つかった値に確定します。

例
-

### Promise.race() の使用

この例では、 `Promise.race()` を使用して、 `setTimeout()` で実装された複数のタイマーを競わせることができることを示しています。最も時間の短いタイマーが常にレースに勝ち、結果のプロミスの状態となります。

```js
function sleep(time, value, state) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (state === "fulfill") {
        return resolve(value);
      } else {
        return reject(new Error(value));
      }
    }, time);
  });
}

const p1 = sleep(500, "one", "fulfill");
const p2 = sleep(100, "two", "fulfill");

Promise.race([p1, p2]).then((value) => {
  console.log(value); // "two"
  // Both fulfill, but p2 is faster
});

const p3 = sleep(100, "three", "fulfill");
const p4 = sleep(500, "four", "reject");

Promise.race([p3, p4]).then(
  (value) => {
    console.log(value); // "three"
    // p3 is faster, so it fulfills
  },
  (error) => {
    // Not called
  },
);

const p5 = sleep(500, "five", "fulfill");
const p6 = sleep(100, "six", "reject");

Promise.race([p5, p6]).then(
  (value) => {
    // Not called
  },
  (error) => {
    console.error(error.message); // "six"
    // p6 is faster, so it rejects
  },
);
```

### Promise.race の非同期性

以下の例では、 `Promise.race` の非同期性を示しています。他のプロミス並行処理メソッドとは異なり、 `Promise.race` は常に非同期です。反復可能オブジェクトが空の場合でも、決して同期的に解決することはありません。

```js
// Promise.race をできるだけ早く起動させるために、
// 解決済みのプロミスの配列を引数として渡しています。
const resolvedPromisesArray = [Promise.resolve(33), Promise.resolve(44)];

const p = Promise.race(resolvedPromisesArray);
// 直ちに p の値を出力
console.log(p);

// setTimeout を使用すると、スタックが空になった後でコードが実行される
setTimeout(() => {
  console.log("スタックが空です");
  console.log(p);
});

// ログ（順番に）:
// Promise { <state>: "pending" }
// スタックが空です
// Promise { <state>: "fulfilled", <value>: 33 }
```

空の反復可能オブジェクトを渡すと、無限に解決しないプロミスが返されます。

```js
const foreverPendingPromise = Promise.race([]);
console.log(foreverPendingPromise);
setTimeout(() => {
  console.log("スタックが空です");
  console.log(foreverPendingPromise);
});

// ログ（順番に）:
// Promise { <state>: "pending" }
// スタックが空です
// Promise { <state>: "pending" }
```

反復可能オブジェクトの中に 1 つ以上のプロミス以外の値や、すでに解決したプロミスが含まれていると、 `Promise.race` は配列の中で見つかった最初のこれらの値で解決します。

```js
const foreverPendingPromise = Promise.race([]);
const alreadyFulfilledProm = Promise.resolve(100);

const arr = [foreverPendingPromise, alreadyFulfilledProm, "non-Promise value"];
const arr2 = [foreverPendingPromise, "non-Promise value", Promise.resolve(100)];
const p = Promise.race(arr);
const p2 = Promise.race(arr2);

console.log(p);
console.log(p2);
setTimeout(() => {
  console.log("スタックが空です");
  console.log(p);
  console.log(p2);
});

// ログ（順番に）
// Promise { <state>: "pending" }
// Promise { <state>: "pending" }
// スタックが空です
// Promise { <state>: "fulfilled", <value>: 100 }
// Promise { <state>: "fulfilled", <value>: "non-Promise value" }
```

### Promise.race() を使用してタイムアウトのリクエストを実装

長くなりそうなリクエストを拒否するタイマーを保有し、制限時間が経過したときに、結果のプロミスが自動的に拒否されるようにレースすることができます。

```js
const data = Promise.race([
  fetch("/api"),
  new Promise((resolve, reject) => {
    // Reject after 5 seconds
    setTimeout(() => reject(new Error("Request timed out")), 5000);
  }),
])
  .then((res) => res.json())
  .catch((err) => displayError(err));
```

`data` のプロミスが履行された場合は、 `/api` から取得されたデータが格納されます。そうでない場合は、 `fetch` が 5 秒間待機していた場合に拒否され、 `setTimeout` タイマーとの競争に負けたことになります。

### Promise.race() を使用してプロミスの状態を検出

`Promise.race()` は反復可能オブジェクトの中で最初に待機していないプロミスに解決するため、待機しているかどうかを含めてプロミスの状態を調べることができます。この例は `promise-status-async` から引用しています。

```js
function promiseState(promise) {
  const pendingState = { status: "pending" };

  return Promise.race([promise, pendingState]).then(
    (value) =>
      value === pendingState ? value : { status: "fulfilled", value },
    (reason) => ({ status: "rejected", reason }),
  );
}
```

この関数では、 `promise` が待機中であれば、 2 つ目の値である `pendingState` が、プロミスではなく、レースの結果になります。それ以外の場合、 `promise` が既に決定されていれば、 `onFulfilled` と `onRejected` ハンドラーによってその状態を知ることができるでしょう。例えば次のようになります。

```js
const p1 = new Promise((res) => setTimeout(() => res(100), 100));
const p2 = new Promise((res) => setTimeout(() => res(200), 200));
const p3 = new Promise((res, rej) => setTimeout(() => rej(300), 100));

async function getStates() {
  console.log(await promiseState(p1));
  console.log(await promiseState(p2));
  console.log(await promiseState(p3));
}

console.log("Immediately after initiation:");
getStates();
setTimeout(() => {
  console.log("After waiting for 100ms:");
  getStates();
}, 100);

// ログ出力:
// Immediately after initiation:
// { status: 'pending' }
// { status: 'pending' }
// { status: 'pending' }
// After waiting for 100ms:
// { status: 'fulfilled', value: 100 }
// { status: 'pending' }
// { status: 'rejected', reason: 300 }
```

**メモ:** `promiseState` 関数は非同期で実行されます。プロミスの値を同期的に取得する方法がないからです（つまり、 `then()` や `await` がない場合）、たとえプロミスが既に決定されていたとしてもです。しかし、`promiseState()` は常に 1 ティック以内に履行され、実際にプロミスの決定を待つことはありません。

### Promise.any() との比較

`Promise.race` は最初に決定された `Promise` を取ります。

```js
const promise1 = new Promise((resolve, reject) => {
  setTimeout(resolve, 500, "one");
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(reject, 100, "two");
});

Promise.race([promise1, promise2])
  .then((value) => {
    console.log("succeeded with value:", value);
  })
  .catch((reason) => {
    // promise1 のみが履行されるが、 promise2 の方が早く決定する
    console.error("failed with reason:", reason);
  });
// failed with reason: two
```

`Promise.any` は最初に履行された `Promise` を取ります。

```js
const promise1 = new Promise((resolve, reject) => {
  setTimeout(resolve, 500, "one");
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(reject, 100, "two");
});

Promise.any([promise1, promise2])
  .then((value) => {
    // promise1 のみが履行されるが、 promise2 の方が早く決定する
    console.log("succeeded with value:", value);
  })
  .catch((reason) => {
    console.error("failed with reason:", reason);
  });
// succeeded with value: one
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-promise.race |

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

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

関連情報
----

* `Promise`
* `Promise.all()`
* `Promise.allSettled()`
* `Promise.any()`


Promise() コンストラクター - JavaScript

Promise() コンストラクター
==================

**`Promise`** コンストラクターは、主にまだプロミスに対応していない関数をラップするために使用します。

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

構文
--

```js
new Promise(executor);
```

### 引数

`executor`

新しい `Promise` オブジェクトを構築する過程でコンストラクターによって呼び出される関数 (`function`) です。 `executor` は結果をプロミスに結びつけるカスタムコードです。プログラマーが `executor` を書きます。この関数の形式は次のようなものであると期待されます。

```js
    function(resolutionFunc, rejectionFunc){
      // 通常は非同期操作です。
    }
```

`resolutionFunc` と `rejectionFunc` も関数で、実際には好きな名前を付けることができます。呼び出し形式は単純で、単一の任意の型の引数を受け付けます。

```js
    resolutionFunc(value) // 解決した時に呼び出し
    rejectionFunc(reason) // 拒否した時に呼び出し
```

`resolutionFunc` の `value` 引数は他のプロミスオブジェクトにすることもでき、そうするとそのプロミスはプロミス連鎖の中に動的に挿入されます。

`executor` については、以下のことを理解することが重要です。

* `executor` の返値は無視されます。
* `executor` の中でエラーが発生した場合、プロミスは拒否されます。

つまり、 `executor` の中のコードが効果を発揮する仕組みは、次のようなものです。

* コンストラクターが新しい `Promise` オブジェクトを生成した時点で、対応する `resolutionFunc` と `rejectionFunc` の一対の関数も生成されます。これらは `Promise` オブジェクトに「結束」されます。
* `executor` 内のコードは、何らかの操作を行う機会を得、その結果を（値が他の Promise オブジェクトでない場合）「解決済み」または「拒否済み」として反映し、それぞれ `resolutionFunc` または `rejectionFunc` を呼び出して終了します。
* つまり、`executor` 内のコードは、 `resolutionFunc` や `rejectionFunc` による副次的影響を介して通信を行います。その副次的影響とは、 `Promise` オブジェクトが「解決済み」または「拒否済み」になることです。

以上のことを踏まえて、典型的な流れをまとめてみました。

1. `executor` の中の操作は非同期であり、コールバックを提供します。
2. コールバックは `executor` コードの中で定義されます。
3. コールバックは `resolutionFunc` を呼び出して終了します。
4. `resolutionFunc` の呼び出しには `value` 引数が含まれます。
5. `value` は繋がっている `Promise` オブジェクトに送り返されます。
6. `Promise` オブジェクトは（非同期に）関連付けられた `.then(handleResolved)` を呼び出します。
7. `.then(handleResolved)` から受け取った `value` は、 `handleResolved` の呼び出しで入力引数として渡されます（プロミスの連鎖を参照してください）。

### 返値

`new` を通じて呼び出された場合、 `Promise` コンストラクターはプロミスオブジェクトを返します。このプロミスオブジェクトは、 `resolutionFunc` 関数または `rejectionFunc` 関数が呼び出されると「解決」になります。なお、 `resolutionFunc` または `rejectionFunc` を別な Promise オブジェクトを引数にして呼び出すと、これが「解決」であると言えますが、「満足」であるとは言えません。

例
-

### 新しい Promise の作成

`Promise` オブジェクトは `new` キーワードとコンストラクターで作成されます。コンストラクターは「executor 関数」と呼ばれる引数を取ります。 これは 2 つの関数を引数として取ります。 1 つ目の関数 (`resolve`) は非同期タスクが成功して完了した場合に呼び出され、タスクの結果を値として返します。2 つ目の関数 (`reject`) はタスクが失敗した場合に呼び出され、失敗した理由（ふつうはエラーオブジェクト）を返します。

```js
const myFirstPromise = new Promise((resolve, reject) => {
  // 次のどちらかを呼び出す非同期処理を行います。
  //
  // resolve(someValue) // 履行
  // または
  // reject("failure reason") // 拒否
});
```

### Promise を返す関数の作成

関数にプロミス機能を提供するには、次のように単にプロミスを返すようにします。

```js
function myAsyncFunction(url) {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open("GET", url);
    xhr.onload = () => resolve(xhr.responseText);
    xhr.onerror = () => reject(xhr.statusText);
    xhr.send();
  });
}
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-promise-constructor |

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

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

関連情報
----

* `Promise` のポリフィルは `core-js` で利用できます
* プロミスの使用


Int32Array() コンストラクター - JavaScript

Int32Array() コンストラクター
=====================

**`Int32Array()`** は型付き配列のコンストラクターで、プラットフォームのバイト順による 2 の補数形式の 32 ビット符号付き整数値の配列を生成します。バイト順の制御が必要な場合は、代わりに `DataView` を使用してください。中身は `0` で初期化されます。生成されると、配列の中の要素はオブジェクトのメソッドを使用するか、配列の標準的な添字の構文を使用するか (すなわち、ブラケット構文を使用するか) して参照することができます。

構文
--
```

new Int32Array(); // new in ES2017
new Int32Array(length);
new Int32Array(typedArray);
new Int32Array(object);
new Int32Array(buffer [, byteOffset [, length]]);
```

### 引数

`length`

`length` 引数付きで呼び出されると、メモリ内に内部的な配列バッファーを作成し、大きさは `length` *を `BYTES_PER_ELEMENT`* で乗じたバイト数になり、ゼロになることもあります。

`typedArray`

`typedArray` 引数付きで呼び出されると、これはあらゆる型付き配列型 (例えば `Int32Array`) にすることができますが、 `typedArray` を新しい型付き配列にコピーします。 `typedArray` の中のそれぞれの値は、新しい配列にコピーされる前にコンストラクターの対応する型に変換されます。新しい型付き配列の長さは `typedArray` 引数の長さと同じになります。

`object`

`object` 引数付きで呼び出されると、あたかも `TypedArray.from()` メソッドであるかのように新しい型付き配列が生成されます。

`buffer`, `byteOffset`, `length`

`buffer` と、オプションで `byteOffset` と `length` 引数を指定して呼び出されると、指定された `ArrayBuffer` を表示する型付き配列ビューが生成されます。 `byteOffset` および `length` 引数は、型付き配列ビューが表示するメモリ範囲を指定する。 両方を省略した場合は `buffer` の全てを表示し、 `length` のみを省略した場合は `buffer` の残りを表示します。

例
-

### 様々な方法による Int32Array の生成

```js
// From a length
var int32 = new Int32Array(2);
int32[0] = 42;
console.log(int32[0]); // 42
console.log(int32.length); // 2
console.log(int32.BYTES\_PER\_ELEMENT); // 4

// From an array
var arr = new Int32Array([21, 31]);
console.log(arr[1]); // 31

// From another TypedArray
var x = new Int32Array([21, 31]);
var y = new Int32Array(x);
console.log(y[0]); // 21

// From an ArrayBuffer
var buffer = new ArrayBuffer(16);
var z = new Int32Array(buffer, 0, 4);

// From an iterable
var iterable = (function\* () {
  yield\* [1, 2, 3];
})();
var int32 = new Int32Array(iterable);
// Int32Array[1, 2, 3]
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-typedarray-constructors |

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

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

### 互換性メモ

ECMAScript 2015 から、 `Int32Array` コンストラクターは構築に `new` 演算子が必要になりました。 `Int32Array` コンストラクターを `new` なしで関数として呼び出すと、 `TypeError` が発生するようになりました。

```js
var dv = Int32Array([1, 2, 3]);
// TypeError: calling a builtin Int32Array constructor
// without new is forbidden
```

```js
var dv = new Int32Array([1, 2, 3]);
```

関連情報
----

* JavaScript 型付き配列
* `ArrayBuffer`
* `DataView`


BigInt.asIntN() - JavaScript

BigInt.asIntN()
===============

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

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

* Learn more
* See full compatibility
* Report feedback
**`BigInt.asIntN`** は静的メソッドで、 BigInt 値を符号付き整数値に丸め、その値を返します。

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

構文
--

```js
BigInt.asIntN(bits, bigint);
```

### 引数

`bits`

整数の大きさのために利用できるビットの数です。

`bigint`

指定されたビット数に丸める BigInt 値です。

### 返値

`bigint` を 2^`bits` で割った剰余の値の符号付き整数です。

例
-

### 64 ビットの範囲に収める

`BigInt.asIntN()` メソッドは、 64 ビットの数値の範囲に収めるのに便利です。

```js
const max = 2n \*\* (64n - 1n) - 1n;

BigInt.asIntN(64, max);
// ↪ 9223372036854775807n

BigInt.asIntN(64, max + 1n);
// ↪ -9223372036854775808n
// オーバーフローするので負数になる
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-bigint.asintn |

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

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

関連情報
----

* `BigInt`
* `BigInt.asUintN()`


BigInt.prototype.toString() - JavaScript

BigInt.prototype.toString()
===========================

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

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

* Learn more
* See full compatibility
* Report feedback
**`toString()`** メソッドは、指定した `BigInt` オブジェクトを表す文字列を返します。末尾の "n" は文字列の一部にはなりません。

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

構文
--

```js
toString();
toString(radix);
```

### 引数

`radix`省略可

オプション。数値を表す底に指定する 2 以上 36 以下の整数（基数）。

### 返値

指定した `BigInt` オブジェクトを表す文字列。

### 例外

`RangeError`

`toString()` に 2 未満または 36 より大きな基数を与えられた場合、`RangeError` が発生します。

解説
--

`BigInt` オブジェクトは `Object` の `toString()` メソッドをオーバーライドします。つまり、 `Object.prototype.toString()` を継承しません。 `BigInt` オブジェクトでは、`toString()` メソッドは指定された基数によるオブジェクトの文字列表現を返します。

`toString()` メソッドは 1 番目の引数を解釈し、指定された基数（底）による文字列表現を返そうとします。10 より大きな基数が指定された場合は、 9 より大きな数値をアルファベットで示します。例えば、16 進数（底が 16）では `a` から `f` が使用されます。

`radix` が指定されなかった場合は、基数として 10 が指定されたとみなします。

`bigIntObj` が負の数だった場合、符号は保持されます。これは、基数が 2 だった場合にも適用されます。つまり、返値の文字列は、`bigIntObj` の正の 2 進数表現の先頭に `-` 符号が付いたものであり、`bigIntObj` の 2 の補数**ではありません。**

例
-

### `toString` の使用

```js
17n.toString(); // '17'
66n.toString(2); // '1000010'
254n.toString(16); // 'fe'
-10n.toString(2); // -1010'
-0xffn.toString(2); // '-11111111'
```

### `BigInt` における負の 0

整数に負の 0 が存在しないのと同様に、`BigInt` には負の 0 がありません。 `-0.0` は JavaScript の `Number` 型にのみ現れる、IEEE 浮動小数点数の概念です。

```js
(-0n).toString(); // '0'
BigInt(-0).toString(); // '0'
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-bigint.prototype.tostring |

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

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

関連情報
----

* `BigInt.prototype.toLocaleString()`
* `BigInt.prototype.valueOf()`
* `Number.prototype.toString()`


BigInt.prototype.valueOf() - JavaScript

BigInt.prototype.valueOf()
==========================

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

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

* Learn more
* See full compatibility
* Report feedback
**`valueOf()`** メソッドは、 `BigInt` オブジェクトにラップされたプリミティブ値を返します。

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

構文
--

```js
bigIntObj.valueOf();
```

### 返値

指定された `BigInt` オブジェクトのプリミティブ値を表す BigInt です。

例
-

### `valueOf` の使用

```js
typeof Object(1n); // object
typeof Object(1n).valueOf(); // bigint
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-bigint.prototype.valueof |

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

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

関連情報
----

* `BigInt.prototype.toString()`


BigInt() コンストラクター - JavaScript

BigInt() コンストラクター
=================

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

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

* Learn more
* See full compatibility
* Report feedback
**`BigInt()`** コンストラクターは **bigint** 型の値を返します。

構文
--

```js
BigInt(value);
```

### 引数

`value`

作成しようとしているオブジェクトの数値。文字列または整数にすることができます。

**メモ:** `BigInt()` は `new` 演算子と共には使用されません。

例
-

### 新しい BigInt の生成

```js
BigInt(123);
// 123n
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-bigint-constructor |

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

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

関連情報
----

* `BigInt` クラス


BigInt.asUintN() - JavaScript

BigInt.asUintN()
================

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

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

* Learn more
* See full compatibility
* Report feedback
**`BigInt.asUintN`** 静的メソッドは、 BigInt 値を符号なし整数に丸め、その値を返します。

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

構文
--

```js
BigInt.asUintN(bits, bigint);
```

### 引数

`bits`

整数の大きさのために利用できるビット数。

`bigint`

指定されたビット数に収めるよう丸める整数値。

返値
--

`bigint` を 2^`bits` で割った剰余の値の符号なし整数です。

例
-

### 64ビットの範囲に収める

`BigInt.asUintN()` メソッドは、64ビットの数値の範囲に収めるのに便利です。

```js
const max = 2n \*\* 64n - 1n;

BigInt.asUintN(64, max);
// ↪ 18446744073709551615n

BigInt.asUintN(64, max + 1n);
// ↪ 0n
// オーバーフローするのでゼロになる
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-bigint.asuintn |

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

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

関連情報
----

* `BigInt`
* `BigInt.asIntN()`


BigInt.prototype.toLocaleString() - JavaScript

BigInt.prototype.toLocaleString()
=================================

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

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

* Learn more
* See full compatibility
* Report feedback
**`toLocaleString()`** メソッドは、この BigInt 値の言語に合わせた表現の文字列を返します。

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

構文
--

```js
toLocaleString();
toLocaleString(locales);
toLocaleString(locales, options);
```

### 引数

`locales` および `options` の引数は、この関数の動作をカスタマイズするためのもので、アプリケーションは整形の慣例を使用する言語を指定することができます。 `locales` や `options` の引数を無視する実装では、使用するロケールや返す文字列の形式はすべて実装に依存します。

これらの引数や使用方法について、詳しくは `Intl.NumberFormat()`
コンストラクター を参照してください。

### 返値

指定された BigInt の言語に合わせた表現の文字列です。

性能
--

大量の数値を整形する場合は、 `Intl.NumberFormat` オブジェクトを生成して `NumberFormat.format` プロパティで提供される関数を使用したほうが有利です。

例
-

### `toLocaleString` の使用

ロケールを使用しない基本的な使用では、既定のロケールと既定のオプションで成形された文字列が返されます。

```js
var bigint = 3500n;

bigint.toLocaleString();
// "3,500" と表示 (U.S. English ロケールの場合)
```

### `locales` の使用

この例ではローカライズされた数値書式の変化形の一部を示しています。アプリケーションのユーザーインターフェイスで使用されている言語の書式を取得するには、必ず `locale` 引きお数でその言語を (場合によっては予備の言語も) 指定してください。

```js
var bigint = 123456789123456789n;

// ドイツ語では千の位の区切りにピリオドを使用
console.log(bigint.toLocaleString("de-DE"));
// → 123.456.789.123.456.789

// 多くのアラビア語を話す国ではアラビア語で東アラビア数字を使用
console.log(bigint.toLocaleString("ar-EG"));
// → ١٢٣٬٤٥٦٬٧٨٩٬١٢٣٬٤٥٦٬٧٨٩

// インドでは千/十万/千万の区切りを使用
console.log(bigint.toLocaleString("en-IN"));
// → 1,23,45,67,89,12,34,56,789

// nu 拡張キーは数値体系を要求。例えば中国語の数字の場合
console.log(bigint.toLocaleString("zh-Hans-CN-u-nu-hanidec"));
// → 一二三,四五六,七八九,一二三,四五六,七八九

// 要求した言語に対応していない場合、例えばバリ語の場合、
// 予備の言語、この場合はインドネシア語を使用
console.log(bigint.toLocaleString(["ban", "id"]));
// → 123.456.789.123.456.789
```

### `options` の使用

`toLocaleString` で提供される結果は `options` 引数でカスタマイズできます。

```js
var bigint = 123456789123456789n;

// 通貨書式を要求
console.log(
  bigint.toLocaleString("de-DE", { style: "currency", currency: "EUR" }),
);
// → 123.456.789.123.456.789,00 €

// 日本円には下位の単位がない
console.log(
  bigint.toLocaleString("ja-JP", { style: "currency", currency: "JPY" }),
);
// → ￥123,456,789,123,456,789

// 有効数字を 3 桁に限定
console.log(bigint.toLocaleString("en-IN", { maximumSignificantDigits: 3 }));
// → 1,23,00,00,00,00,00,00,000
```

仕様書
---

| Specification |
| --- |
| ECMAScript Internationalization API Specification # sup-bigint.prototype.tolocalestring |

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

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

関連情報
----

* `BigInt.toString()`


ArrayBuffer.isView() - JavaScript

ArrayBuffer.isView()
====================

**`ArrayBuffer.isView()`** メソッドは、渡された値が `ArrayBuffer` のビューのうちの一つ、例えば型付き配列オブジェクトや `DataView` であるかどうかを判断します。

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

構文
--

```js
ArrayBuffer.isView(value)
```

### 引数

`value`

チェックする値です。

### 返値

渡された引数が `ArrayBuffer` のビューのうちの一つであれば `true` を、そうでなければ `false` を返します。

例
-

### isView の使用

```js
ArrayBuffer.isView(); // false
ArrayBuffer.isView([]); // false
ArrayBuffer.isView({}); // false
ArrayBuffer.isView(null); // false
ArrayBuffer.isView(undefined); // false
ArrayBuffer.isView(new ArrayBuffer(10)); // false

ArrayBuffer.isView(new Uint8Array()); // true
ArrayBuffer.isView(new Float32Array()); // true
ArrayBuffer.isView(new Int8Array(10).subarray(0, 3)); // true

const buffer = new ArrayBuffer(2);
const dv = new DataView(buffer);
ArrayBuffer.isView(dv); // true
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-arraybuffer.isview |

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

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

関連情報
----

* JavaScript の型付き配列


ArrayBuffer() コンストラクター - JavaScript

ArrayBuffer() コンストラクター
======================

**`ArrayBuffer()`** コンストラクターは `ArrayBuffer` オブジェクトを生成するために使用されます。

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

構文
--

```js
new ArrayBuffer(length)
new ArrayBuffer(length, options)
```

**メモ:** `ArrayBuffer()` は `new` でのみ構築することができます。`new` 無しで呼び出そうとすると、`TypeError` が発生します。

### 引数

`length`

作成する配列バッファーのサイズをバイト単位で指定します。

`options` 省略可
Experimental

オブジェクトであり、以下のプロパティを持つことができます。

`maxByteLength` 省略可
Experimental

配列バッファーがサイズ変更可能な最大サイズ（バイト単位）。

### 返値

指定したサイズの新しい `ArrayBuffer` オブジェクト。その `maxByteLength` プロパティには、`maxByteLength` を指定した場合はその値が設定されます。内容は 0 に初期化されます。

### 例外

`RangeError`

以下のいずれかに該当する場合に発生します。

* `length` または `maxByteLength` が `Number.MAX_SAFE_INTEGER` (≥ 253) より大きいか、負の数である。
* `length` が `maxByteLength` より大きい。

例
-

### ArrayBuffer の作成

この例では、バッファーを参照する `Int32Array` ビューを持つ 8 バイトのバッファーを作成しています。

```js
const buffer = new ArrayBuffer(8);
const view = new Int32Array(buffer);
```

### サイズ変更可能な ArrayBuffer の作成

この例では、最大 16 バイトまでリサイズ可能な 8 バイトのバッファーを作成し、`resize()` でそれを 12 バイトにサイズ変更しています。

```js
const buffer = new ArrayBuffer(8, { maxByteLength: 16 });

buffer.resize(12);
```

**メモ:** `maxByteLength` は使用する用途に応じて使用可能な最小値に設定することが推奨されます。メモリ不足になる危険を縮小するために、`1073741824` (1GB) を超えないようにする必要があります。

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-arraybuffer-constructor |

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

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

関連情報
----

* `ArrayBuffer` のポリフィル (`core-js`)
* JavaScript 型付き配列
* `SharedArrayBuffer`


ArrayBuffer.prototype.byteLength - JavaScript

ArrayBuffer.prototype.byteLength
================================

**`byteLength`** アクセサープロパティは、`ArrayBuffer` の長さをバイト単位で表します。

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

解説
--

`byteLength` プロパティはアクセサープロパティで、設定アクセサー関数が `undefined` であるため、このプロパティは読み取ることしかできません。値は配列が構築されるときに設定され、変更することができません。この `ArrayBuffer` が取り外された場合、このプロパティは 0 を返します。

例
-

### byteLength の使用

```js
const buffer = new ArrayBuffer(8);
buffer.byteLength; // 8
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-get-arraybuffer.prototype.bytelength |

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

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

関連情報
----

* `ArrayBuffer`


ArrayBuffer.prototype.maxByteLength - JavaScript

ArrayBuffer.prototype.maxByteLength
===================================

**Experimental:** **これは実験的な機能です。**
本番で使用する前にブラウザー互換性一覧表をチェックしてください。

**`maxByteLength`** は `ArrayBuffer` インスタンスのアクセサープロパティで、`ArrayBuffer` がサイズ変更可能な最大長をバイト数で表します。

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

解説
--

`maxByteLength` プロパティはアクセサープロパティであり、その設定アクセサー関数が `undefined` であるため、このプロパティは読み取ることしかできません。この値は配列の構築時に、 `maxByteLength` オプションを `ArrayBuffer()` コンストラクターで設定した際に設定され、変更することができません。

このプロパティは、この `ArrayBuffer` が切り離されている場合は 0 を返し ます。この `ArrayBuffer` が `maxByteLength` の値を指定せずに構築された場合、このプロパティは `ArrayBuffer` の `byteLength` の値と等しい値を返します。

例
-

### maxByteLength の使用

この例では、最大 16 バイトまでサイズ変更可能な 8 バイトのバッファーが作成され、その`maxByteLength`を返しています。

```js
const buffer = new ArrayBuffer(8, { maxByteLength: 16 });

buffer.maxByteLength; // 16
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-get-arraybuffer.prototype.maxbytelength |

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

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

関連情報
----

* `ArrayBuffer`
* `ArrayBuffer.prototype.byteLength`
* `ArrayBuffer.prototype.resize()`


ArrayBuffer.prototype.resizable - JavaScript

ArrayBuffer.prototype.resizable
===============================

**Experimental:** **これは実験的な機能です。**
本番で使用する前にブラウザー互換性一覧表をチェックしてください。

**`resizable`** は `ArrayBuffer` インスタンスのアクセサープロパティで、この `ArrayBuffer` がサイズ変更かどうかを表します。

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

解説
--

`resizable` プロパティはアクセサープロパティであり、設定アクセサー関数が `undefined` であるためこのプロパティは読み取ることしかできません。この値は、この配列が構築されるときに確定されます。コンストラクターで `maxByteLength` オプションが設定されていれば `resizable` は `true` を返し、そうでなければ `false` を返します。

例
-

### resizable の使用

この例では、最大 16 バイトの長さにサイズ変更可能な 8 バイトのバッファーを作成し、`resizable` プロパティを調べて、`resizable` が true を返す場合にサイズ変更します。

```js
const buffer = new ArrayBuffer(8, { maxByteLength: 16 });

if (buffer.resizable) {
  console.log("Buffer is resizable!");
  buffer.resize(12);
}
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-get-arraybuffer.prototype.resizable |

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

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

関連情報
----

* `ArrayBuffer`
* `ArrayBuffer.prototype.maxByteLength`
* `ArrayBuffer.prototype.resize()`


ArrayBuffer.prototype.slice() - JavaScript

ArrayBuffer.prototype.slice()
=============================

**`slice()`** メソッドは新しい `ArrayBuffer` を返し、その中にこの `ArrayBuffer` の `begin` から `end` の手前までをコピーします。

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

構文
--

```js
slice(begin)
slice(begin, end)
```

### 引数

`begin`

スライスの起点を表すゼロ基点のバイトインデックスです。

`end` 省略可

スライスがその前で終了するバイトインデックスです。end を指定しなかった場合、新しい `ArrayBuffer` は、この `ArrayBuffer` の起点から終点まですべてのバイトを含みます。

### 返値

新しい `ArrayBuffer` オブジェクト。

解説
--

`slice()` メソッドは、`end` 引数で指定されたバイトの手前までコピーを行います。`begin` または `end` のどちらかが負の数の場合は、開始位置とは反対に、配列の末尾からのインデックスを参照します。

`begin` および `end` 引数で指定された範囲は、現在の配列で妥当なインデックスの範囲に丸められます。新しい `ArrayBuffer` の計算された長さが負の数であった場合、ゼロに丸められます。

例
-

### ArrayBuffer のコピー

```js
const buf1 = new ArrayBuffer(8);
const buf2 = buf1.slice(0);
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-arraybuffer.prototype.slice |

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

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

関連情報
----

* `ArrayBuffer`


get ArrayBuffer[@@species] - JavaScript

get ArrayBuffer[@@species]
==========================

**`ArrayBuffer[@@species]`** は静的アクセサープロパティで、配列バッファーメソッドから返値を作成するために使用されるコンストラクタを返します。

**警告:** `@@species` が存在することで、任意のコードを実行することができ、セキュリティ上の脆弱性を⽣じる可能性があります。また、ある種の最適化もとても難しくなります。エンジンの実装者はこの機能を削除するかどうかを調査しています。可能であれば、この機能に頼らないでください。

構文
--

```js
ArrayBuffer[Symbol.species];
```

### 返値

`get @@species` が呼び出されたコンストラクター (`this`) の値です。この返値は、新しい配列バッファーを作成する配列バッファーのメソッドから返値を作成するために使用されます。

解説
--

`@@species` アクセサープロパティは、既定のコンストラクターである `ArrayBuffer` オブジェクトを返します。サブクラスのコンストラクターはコンストラクターに代入することで、これをオーバーライドできます。

```js
// 説明のための仮想の基盤実装
class ArrayBuffer {
  static get [Symbol.species]() {
    return this;
  }
}
```

この 多態的な実装のために、派生したサブクラスの `@@species` も既定値ではコンストラクター自身を返すことになります。

```js
class SubArrayBuffer extends ArrayBuffer {}
SubArrayBuffer[Symbol.species] === SubArrayBuffer; // true
```

既存のオブジェクトを変異させず、新しい配列バッファーのインスタンスを返す配列バッファーのメソッド（例: `slice()`) を呼び出す場合、オブジェクトの `constructor[@species]` にアクセスすることになります。返されたコンストラクターは、配列バッファーメソッドの返値を構成するために使用されます。

例
-

### 通常のオブジェクトの spicies

species プロパティは、`ArrayBuffer` オブジェクトの既定のコンストラクター関数である `ArrayBuffer` コンストラクターを返します。

```js
ArrayBuffer[Symbol.species]; // ArrayBuffer() 関数
```

### 派生オブジェクトの spicies

派生コレクションオブジェクト（たとえば、独自の配列バッファーである `MyArrayBuffer`）では、`MyArrayBuffer` の species は `MyArrayBuffer` コンストラクターです。しかし、派生クラスのメソッドで、親である `ArrayBuffer` オブジェクトを返すためにこれをオーバーライドしたいかもしれません。

```js
class MyArrayBuffer extends ArrayBuffer {
  // MyArrayBuffer species を親である ArrayBuffer コンストラクタにオーバーライド。
  static get [Symbol.species]() {
    return ArrayBuffer;
  }
}
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-get-arraybuffer-@@species |

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

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

関連情報
----

* `ArrayBuffer`
* `Symbol.species`


ArrayBuffer.prototype.resize() - JavaScript

ArrayBuffer.prototype.resize()
==============================

**Experimental:** **これは実験的な機能です。**
本番で使用する前にブラウザー互換性一覧表をチェックしてください。

**`resize()`** は `ArrayBuffer` インスタンスのメソッドで、この `ArrayBuffer` を指定されたサイズ（バイト単位）にサイズ変更します。

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

構文
--

```js
resize(newLength)
```

### 引数

`newLength`

`ArrayBuffer` のサイズを変更する新しい長さ（バイト単位）です。

### 返値

`undefined` です。

### 例外

`TypeError`

`ArrayBuffer` が切り離されているか、サイズ変更できない場合に発生します。

`RangeError`

`newLength`が `ArrayBuffer` の `maxByteLength` より大きい場合に発生します。

解説
--

`resize()` メソッドは `ArrayBuffer` を `newLength` 引数で指定された大きさへサイズ変更します。 ただし、`ArrayBuffer` がサイズ変更可能で、新しいサイズが `ArrayBuffer` の `maxByteLength` 以下であることが条件です。新しいバイトは 0 に初期化されます。

また、`resize()` を使用すると、`ArrayBuffer` を成長させるだけでなく、縮小させることができることに注意してください。`newLength` が `ArrayBuffer` の現在の `byteLength` より小さくなることが許容されています。

例
-

### resize() の使用

この例では、最大16バイトの長さにサイズ変更可能な8バイトのバッファーを作成し、`resizable` プロパティを調べて、`resizable` が true を返した場合にサイズを変更します。

```js
const buffer = new ArrayBuffer(8, { maxByteLength: 16 });

if (buffer.resizable) {
  console.log("Buffer is resizable!");
  buffer.resize(12);
}
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-arraybuffer.prototype.resize |

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

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

関連情報
----

* `ArrayBuffer`
* `ArrayBuffer.prototype.resizable`
* `ArrayBuffer.prototype.maxByteLength`


JSON.parse() - JavaScript

JSON.parse()
============

**`JSON.parse()`** メソッドは文字列を JSON として解析し、文字列によって記述されている JavaScript の値やオブジェクトを構築します。任意の **reviver** 関数で、生成されたオブジェクトが返される前に変換を実行することができます。

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

構文
--

```js
JSON.parse(text);
JSON.parse(text, reviver);
```

### 引数

`text`

JSON として解析する文字列。JSON の構文の説明は `JSON` オブジェクトを参照してください。

`reviver` 省略可

もし関数である場合、解析により作り出された元の値を、オブジェクトを返す前に変換する方法を指示します。

### 返値

`Object`, `Array`, 文字列, 数値, 論理値, null 値のいずれかで、指定された JSON の `text` に対応する値です。

### 例外

解析する文字列が有効な JSON でない場合、`SyntaxError` 例外が発生します。

ポリフィル
-----

```js
// From https://github.com/douglascrockford/JSON-js/blob/master/json2.js
if (typeof JSON.parse !== "function") {
  var rx_one = /^[\],:{}\s]\*$/;
  var rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
  var rx_three =
    /"[^"\\\n\r]\*"|true|false|null|-?\d+(?:\.\d\*)?(?:[eE][+\-]?\d+)?/g;
  var rx_four = /(?:^|:|,)(?:\s\*\[)+/g;
  var rx_dangerous =
    /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
  JSON.parse = function (text, reviver) {
    // The parse method takes a text and an optional reviver function, and returns
    // a JavaScript value if the text is a valid JSON text.

    var j;

    function walk(holder, key) {
      // The walk method is used to recursively walk the resulting structure so
      // that modifications can be made.

      var k;
      var v;
      var value = holder[key];
      if (value && typeof value === "object") {
        for (k in value) {
          if (Object.prototype.hasOwnProperty.call(value, k)) {
            v = walk(value, k);
            if (v !== undefined) {
              value[k] = v;
            } else {
              delete value[k];
            }
          }
        }
      }
      return reviver.call(holder, key, value);
    }

    // Parsing happens in four stages. In the first stage, we replace certain
    // Unicode characters with escape sequences. JavaScript handles many characters
    // incorrectly, either silently deleting them, or treating them as line endings.

    text = String(text);
    rx_dangerous.lastIndex = 0;
    if (rx_dangerous.test(text)) {
      text = text.replace(rx_dangerous, function (a) {
        return "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4);
      });
    }

    // In the second stage, we run the text against regular expressions that look
    // for non-JSON patterns. We are especially concerned with "()" and "new"
    // because they can cause invocation, and "=" because it can cause mutation.
    // But just to be safe, we want to reject all unexpected forms.

    // We split the second stage into 4 regexp operations in order to work around
    // crippling inefficiencies in IE's and Safari's regexp engines. First we
    // replace the JSON backslash pairs with "@" (a non-JSON character). Second, we
    // replace all simple value tokens with "]" characters. Third, we delete all
    // open brackets that follow a colon or comma or that begin the text. Finally,
    // we look to see that the remaining characters are only whitespace or "]" or
    // "," or ":" or "{" or "}". If that is so, then the text is safe for eval.

    if (
      rx_one.test(
        text.replace(rx_two, "@").replace(rx_three, "]").replace(rx_four, ""),
      )
    ) {
      // In the third stage we use the eval function to compile the text into a
      // JavaScript structure. The "{" operator is subject to a syntactic ambiguity
      // in JavaScript: it can begin a block or an object literal. We wrap the text
      // in parens to eliminate the ambiguity.

      j = eval("(" + text + ")");

      // In the optional fourth stage, we recursively walk the new structure, passing
      // each name/value pair to a reviver function for possible transformation.

      return typeof reviver === "function"
        ? walk(
            {
              "": j,
            },
            "",
          )
        : j;
    }

    // If the text is not JSON parsable, then a SyntaxError is thrown.

    throw new SyntaxError("JSON.parse");
  };
}
```

例
-

### JSON.parse() の使用

```js
JSON.parse("{}"); // {}
JSON.parse("true"); // true
JSON.parse('"foo"'); // "foo"
JSON.parse('[1, 5, "false"]'); // [1, 5, "false"]
JSON.parse("null"); // null
```

### reviver 引数の使用

`reviver` が指定された場合、解析によって計算された値は、返却される前に*変換*されます。具体的には、計算された値とそのすべてのプロパティ (最も深いプロパティから始まり、元の値自身に至るまで) は、個別に `reviver` を通して変換されます。そして、処理されるプロパティを含むオブジェクトを `this` とし、プロパティ名を文字列、プロパティ値を引数にして、これが呼び出されます。もし `reviver` 関数が `undefined` を返した場合 (または、値を返さなかった場合、例えば関数の途中で実行が中断された場合など)、そのプロパティはオブジェクトから削除されます。そうでなければそのプロパティは返値として再定義されます。

もし `reviver` が一部の値だけを変換して他を変換しないのであれば、必ずすべての変換されない値をそのまま返すようにしてください。そうしなければ、結果として得られるオブジェクトから削除されてしまいます。

```js
JSON.parse(
  '{"p": 5}',
  (key, value) =>
    typeof value === "number"
      ? value \* 2 // 数値ならば値の2倍を返す
      : value, // それ以外ならば変更しない
);

// { p: 10 }

JSON.parse('{"1": 1, "2": 2, "3": {"4": 4, "5": {"6": 6}}}', (key, value) => {
  console.log(key); // 現在のプロパティ名を出力する。最後は ""。
  return value; // 変更されていないプロパティの値を返す。
});

// 1
// 2
// 4
// 6
// 5
// 3
// ""
```

### JSON.parse() は末尾のカンマを許容しない

```js
// 両方とも SyntaxError が発生
JSON.parse("[1, 2, 3, 4, ]");
JSON.parse('{"foo" : 1, }');
```

### JSON.parse() は単一引用符を許容しない

```js
// SyntaxError が発生
JSON.parse("{'foo': 1}");
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-json.parse |

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

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

関連情報
----

* `JSON.stringify()`


JSON.stringify() - JavaScript

JSON.stringify()
================

**`JSON.stringify()`** メソッドは、ある JavaScript のオブジェクトや値を JSON 文字列に変換します。置き換え関数を指定して値を置き換えたり、置き換え配列を指定して指定されたプロパティのみを含むようにしたりすることもできます。

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

構文
--

```js
JSON.stringify(value)
JSON.stringify(value, replacer)
JSON.stringify(value, replacer, space)
```

### 引数

`value`

JSON 文字列に変換する値です。

`replacer` 省略可

文字列化の手順の挙動を変更する関数、または `value` のプロパティのうち出力に含めるものを指定する `String` と `Number` の配列です。この値が配列である場合は、文字列でも数値でもない要素 (`Symbol` など) は完全に無視されます。文字列や数値としては、プリミティブもラッパーオブジェクトも使用可能です。この値が関数でも配列でもない場合 (`null` の場合や、指定しない場合など) は、結果の JSON 文字列にオブジェクトの文字列をキーとするすべてのプロパティが含まれます。

`space` 省略可

出力する JSON 文字列に可読性を目的に空白 (インデントや改行など) を挿入するために使う `String` または `Number` オブジェクトです。

これが `Number` のときは、インデントとして使う空白文字の数を示します。この数の上限は 10 です (それより大きい数値は、単に `10` となります)。 1 より小さい値は空白を使わないことを示します。

これが `String` のときは、その文字列 (10 文字より長い場合はその最初の 10 文字) がネストされたそれぞれのオブジェクトや配列の前に挿入されます。

これが文字列でも数値でもない (文字列や数値としては、プリミティブもラッパーオブジェクトも使用可能) 場合、たとえば `null` や指定しない場合は、空白は使用されません。

### 返値

与えられた値を表現する JSON 文字列。

### 例外

* `TypeError` ("cyclic object value") 例外は、循環参照が見つかった時に発生します。
* `TypeError` ("BigInt value can't be serialized in JSON") 例外は、 `BigInt` 値を文字列化しようとしたときに発生します。
説明
--

`JSON.stringify()` は値をそれを表す JSON 表記に変換します。値は以下のように変換されます。

* `Boolean`、 `Number`、 `String`、および (`Object()` により得られる) `BigInt` の各オブジェクトは、文字列化の際に慣習的な変換セマンティクスに従い、対応するプリミティブ値に変換されます。(`Object()` により得られる) `Symbol` のオブジェクトは、プレーンオブジェクトとして扱われます。
* `BigInt` の値を文字列化しようとすると、例外が発生します。しかし、`BigInt` が (モンキーパッチ `BigInt.prototype.toJSON = ...` により) `toJSON()` メソッドを持っている場合、このメソッドにより文字列化できます。この制約により、適切な文字列化の方法 (そして、ほとんどの場合、対応する逆変換の方法) が常にユーザーによって明示されるようにします。
* `undefined`、関数 (`Function`)、シンボル (`Symbol`) は有効な JSON 値ではありません。変換中にそのような値に遭遇した場合は、(オブジェクトの中で発見された場合は) 省略されたり、(配列の中で見つかった場合は) `null` に変換されたりします。 `JSON.stringify()` は `JSON.stringify(() => {})` や `JSON.stringify(undefined)` のように「純粋」な値を渡した場合に `undefined` を返すことがあります。
* `Infinity` および `NaN` の数値は、 `null` の値と同様に、すべて `null` と見なされます。(ただし、前述の値と違って、省略されることはありません)
* 配列は配列として文字列化されます。(角括弧で囲まれます) 0 から `length - 1` までの添字 (両端を含みます) が文字列化され、他のプロパティは無視されます。
* その他のオブジェクトについては:
    + シンボル (`Symbol`) がキーとなっているプロパティはすべて、引数 `replacer` を使用する場合でも完全に無視されます。
    + 値が `toJSON()` メソッドを持っている場合は、それがデータをどう文字列化するかを決定します。オブジェクトを文字列化するかわりに、`toJSON()` メソッドが返す値が文字列化されます。`JSON.stringify()` は `toJSON` を 1 個の引数 `key` を指定して呼び出します。この引数は、`replacer` 関数と同じ以下の仕様です:
        - オブジェクトがプロパティの値の場合は、プロパティ名
        - 配列の要素の場合は、配列の添字を表す文字列
        - `JSON.stringify()` がこのオブジェクトについて直接呼ばれた場合は、空文字列
    + `Date` のインスタンスは文字列を返す `toJSON()` を実装しています (`date.toISOString()` と同じです)。そのため、これは文字列に変換されます。
    + 列挙可能なプロパティのみが文字列化されます。そのため、`Map`、`Set`、`WeakMap`、`WeakSet` などは `"{}"` に変換されます。引数 `replacer` を用いることで、これらをより実用的なものに変換できます。プロパティは、`Object.keys()` と同じアルゴリズムで走査されます。このアルゴリズムは、完全に定義された順番を用い、実装間で一貫性があります。例えば、`JSON.stringify` を同じオブジェクトに対して用いると、常に同じ文字列を生成します。また、`JSON.parse(JSON.stringify(obj))` は (オブジェクトが完全に JSON に変換可能であると仮定すると) もとのオブジェクトと同じキーの順番を持つオブジェクトを生成します。
### replacer 引数

`replacer` 引数は関数または配列です。

配列の場合、その要素は結果の JSON 文字列に含めるオブジェクトのプロパティの名前を表します。文字列と数値である値のみが処理に用いられ、シンボルのキーは無視されます。

関数の場合、`key` と文字列化される `value` の 2 つの引数を取ります。キーをもつオブジェクトが `replacer` のコンテキストで `this` として提供されます。

`replacer` 関数は、まず文字列化されるオブジェクトについて呼び出され、このときの `key` は空文字列 (`""`) です。その後、文字列化されるオブジェクトや配列のそれぞれのプロパティについて呼び出されます。配列の添字は、文字列として `key` に入ります。処理中のプロパティの値は、文字列化において `replacer` の返値に置き換えられます。すなわち:

* 数値 (`Number`)、文字列 (`String`)、論理値 (`Boolean`)、`null` を返すと、その値を直接文字列化したものがプロパティの値として使用されます。(`BigInt` を返すと、例外が発生します)
* 関数 (`Function`)、シンボル (`Symbol`)、`undefined` を返すと、出力にはそのプロパティが含まれなくなります。
* その他のオブジェクトを返した場合、そのオブジェクトのそれぞれのプロパティに `replacer` 関数を呼び出して再帰的に文字列化します。

**メモ:** `replacer` 関数を使用して配列から値を削除することはできません。`undefined` や関数を返すと、代わりに `null` が使用されます。

**メモ:** `replacer` が、オブジェクトが初期状態であるか、空文字列のキーを持つプロパティであるかを判別するには (どちらの場合もキーが空文字列になり、オブジェクトが値になる可能性があるので)、繰り返し回数を追跡しておく必要があります (繰り返しが 1 回を超えた場合、空文字列のキーであることが分かります)。

**メモ:** `replacer` 関数を用いて生成した JSON をパースする際は、逆変換のために引数 `reviver` を用いたくなる可能性が高いでしょう。

通常、配列の要素の添字はずれません (要素が関数などの無効な値である場合も、省略されるのではなく `null` になります)。`replacer` 関数を用いると、別の配列を返すことで、配列の要素の順番を制御できます。

### space 引数

`space` 引数で最終的な文字列での空白の数を調整できます。

* 数値であれば、レベルの階層がそれぞれその数の空白文字 (最大 10 文字) でインデントされます。
* 文字列であれば、レベルの階層がそれぞれこの文字列 (またはその最初の 10 文字) でインデントされます。

インデントの階層が 10 より長くなることはありません。`space` の値が数値の場合は最大 10 となり、文字列の場合は 10 文字に切り詰められます。

例
-

### JSON.stringify の使用

```js
JSON.stringify({}); // '{}'
JSON.stringify(true); // 'true'
JSON.stringify("foo"); // '"foo"'
JSON.stringify([1, "false", false]); // '[1,"false",false]'
JSON.stringify([NaN, null, Infinity]); // '[null,null,null]'
JSON.stringify({ x: 5 }); // '{"x":5}'

JSON.stringify(new Date(2006, 0, 2, 15, 4, 5));
// '"2006-01-02T15:04:05.000Z"'

JSON.stringify({ x: 5, y: 6 });
// '{"x":5,"y":6}'
JSON.stringify([new Number(3), new String("false"), new Boolean(false)]);
// '[3,"false",false]'

// 文字列がキーとなった配列要素は列挙可能ではなく、JSON では意味をなさない
let a = ["foo", "bar"];
a["baz"] = "quux"; // a: [ 0: 'foo', 1: 'bar', baz: 'quux' ]
JSON.stringify(a);
// '["foo","bar"]'

JSON.stringify({ x: [10, undefined, function () {}, Symbol("")] });
// '{"x":[10,null,null,null]}'

// 標準データ構造
JSON.stringify([
  new Set([1]),
  new Map([[1, 2]]),
  new WeakSet([{ a: 1 }]),
  new WeakMap([[{ a: 1 }, 2]]),
]);
// '[{},{},{},{}]'

// 型付き配列
JSON.stringify([new Int8Array([1]), new Int16Array([1]), new Int32Array([1])]);
// '[{"0":1},{"0":1},{"0":1}]'
JSON.stringify([
  new Uint8Array([1]),
  new Uint8ClampedArray([1]),
  new Uint16Array([1]),
  new Uint32Array([1]),
]);
// '[{"0":1},{"0":1},{"0":1},{"0":1}]'
JSON.stringify([new Float32Array([1]), new Float64Array([1])]);
// '[{"0":1},{"0":1}]'

// toJSON()
JSON.stringify({
  x: 5,
  y: 6,
  toJSON() {
    return this.x + this.y;
  },
});
// '11'

// シンボル:
JSON.stringify({ x: undefined, y: Object, z: Symbol("") });
// '{}'
JSON.stringify({ [Symbol("foo")]: "foo" });
// '{}'
JSON.stringify({ [Symbol.for("foo")]: "foo" }, [Symbol.for("foo")]);
// '{}'
JSON.stringify({ [Symbol.for("foo")]: "foo" }, (k, v) => {
  if (typeof k === "symbol") {
    return "a symbol";
  }
});
// undefined

// 列挙可能でないプロパティ:
JSON.stringify(
  Object.create(null, {
    x: { value: "x", enumerable: false },
    y: { value: "y", enumerable: true },
  }),
);
// '{"y":"y"}'

// BigInt の値は例外が発生
JSON.stringify({ x: 2n });
// TypeError: BigInt value can't be serialized in JSON
```

### replacer として関数を用いる例

```js
function replacer(key, value) {
  // プロパティをフィルターする
  if (typeof value === "string") {
    return undefined;
  }
  return value;
}

var foo = {
  foundation: "Mozilla",
  model: "box",
  week: 45,
  transport: "car",
  month: 7,
};
JSON.stringify(foo, replacer);
// '{"week":45,"month":7}'
```

`replacer` で最初のオブジェクトと空文字列をキーとするプロパティを区別したい場合は、(両方の場合において `key` は空文字列となり、`value` はオブジェクトを取りうるので) 繰り返しの回数の記録が必要になるでしょう。(最初の繰り返しより後の場合、本当に空文字列のキーです)

```js
function makeReplacer() {
  let isInitial = true;

  return (key, value) => {
    if (isInitial) {
      isInitial = false;
      return value;
    }
    if (key === "") {
      // (最初のオブジェクト以外の) 名前が "" であるプロパティをすべて取り除く
      return undefined;
    }
    return value;
  };
}

const replacer = makeReplacer();
console.log(JSON.stringify({ "": 1, b: 2 }, replacer)); // "{"b":2}"
```

### replacer として配列を用いる例

`replacer` が配列である場合、その配列の値は結果の JSON 文字列に含めるプロパティの名前を示します。

```js
JSON.stringify(foo, ["week", "month"]);
// '{"week":45,"month":7}', "week" と "month" プロパティだけが保持される
```

### 引数 space の使用

出力をスペース 1 個でインデントします。

```js
console.log(JSON.stringify({ a: 2 }, null, " "));
/\*
'{
 "a": 2
}'
\*/
```

タブ文字を使うと、標準的な表示の整形と同様になります。

```js
console.log(JSON.stringify({ uno: 1, dos: 2 }, null, "\t"));
// 以下の文字列を返します:
/\*
{
 "uno": 1,
 "dos": 2
}
\*/
```

### toJSON() の挙動

オブジェクトに `toJSON()` を定義することで、シリアライズの挙動をオーバーライドできます。

文字列化されるオブジェクトに `toJSON` という名前の値に関数を持ったプロパティがある場合、その `toJSON()` メソッドで JSON の文字列化の挙動をカスタマイズできます。シリアライズされるオブジェクトの代わりに、その `toJSON()` メソッドが呼び出されたときの返値がシリアライズされます。 `JSON.stringify()` は `toJSON` に以下のどれか 1 つの引数をつけて呼び出します。

* このオブジェクトがプロパティの値であった場合は、プロパティ名
* 配列内の値であった場合は、文字列化した配列のインデックス
* `JSON.stringify()` がこのオブジェクトに対して直接呼び出された場合は、空文字列

例

```js
var obj = {
  data: "data",

  toJSON(key) {
    if (key) return `Now I am a nested object under key '${key}'`;
    else return this;
  },
};

JSON.stringify(obj);
// '{"data":"data"}'

JSON.stringify({ obj }); // Shorthand property names (ES2015).
// '{"obj":"Now I am a nested object under key 'obj'"}'

JSON.stringify([obj]);
// '["Now I am a nested object under key '0'"]'
```

### 循環参照をシリアライズした場合の JSON.stringify() に関する問題

JSON 形式はオブジェクト参照に対応していないため (IETF 草稿はありますが)、循環参照のあるオブジェクトをエンコードしようとすると `TypeError` が発生します。

```js
const circularReference = {};
circularReference.myself = circularReference;

// 循環参照をシリアライズすると "TypeError: cyclic object value" が発生
JSON.stringify(circularReference);
```

循環参照をシリアライズするためには、これに対応したライブラリを使用したり (Douglas Crockford による cycle.js など)、自分自身で解決策を実装したりする方法があります。循環参照を探索してシリアライズされた値に置き換える (または削除する) 必要があるでしょう。

`JSON.stringify()` をオブジェクトをディープコピーするために使っている場合は、かわりに `structuredClone()` を使いたくなるかもしれません。この関数は循環参照に対応しています。`v8.serialize()` などのバイナリシリアライズを行う JavaScript エンジンの API も、循環参照に対応しています。

### JSON.stringify をそのまま JavaScript として使用する際の問題

従来、JSON は JavaScript の完全に厳密なサブセットではありませんでした。文字コードポイント U+2028 LINE SEPARATOR (改行) と U+2029 PARAGRAPH SEPARATOR (改段落) は JSON テキスト内の文字列リテラルやプロパティ名に使用することができます。しかし、JavsScript のテキスト内で同様の文脈では使用することができず、Unicode エスケープを使用した `\u2028` および `\u2029` しか使うことができません。これは最近変更され、どちらのコードポイントも JSON と JavaScript の両方の文字列で使用することができるようになりました。

したがって、古い JavaScript エンジンとの互換性が必要な場合は、`JSON.stringify` から返された文字列を JavaScript の文字列に代入するために、直接 `eval` や `new Function` に渡したり、JSONP URL の一部として用いたりするのは危険です。次のユーティリティを使用することができます。

```js
function jsFriendlyJSONStringify(s) {
  return JSON.stringify(s)
    .replace(/\u2028/g, "\\u2028")
    .replace(/\u2029/g, "\\u2029");
}

var s = {
  a: String.fromCharCode(0x2028),
  b: String.fromCharCode(0x2029),
};
try {
  eval("(" + JSON.stringify(s) + ")");
} catch (e) {
  console.log(e); // "SyntaxError: unterminated string literal"
}

// catch する必要はない
eval("(" + jsFriendlyJSONStringify(s) + ")");

// Firefox での console.log はコンソールにログ出力をする場合
// Unicode エスケープを解除するので、alert を使う
alert(jsFriendlyJSONStringify(s)); // {"a":"\u2028","b":"\u2029"}
```

**メモ:** 配列以外のオブジェクトのプロパティでは、特定の順番で文字列化されることは保証されていません。文字列化された同じオブジェクトの中でプロパティの順番に依存しないようにしてください。

```js
var a = JSON.stringify({ foo: "bar", baz: "quux" });
//'{"foo":"bar","baz":"quux"}'
var b = JSON.stringify({ baz: "quux", foo: "bar" });
//'{"baz":"quux","foo":"bar"}'
console.log(a !== b); // true

// 一部の記憶関数は JSON.stringify を使用して引数をシリアライズしており、
// 上記のような同じオブジェクトに出会った時にキャッチし損ねることがあります
```

### localStorage で JSON.stringify() を使った例

ユーザーが作成したオブジェクトを格納し、ブラウザーが閉じた後に復元できるようにしたい場合は以下の例が `JSON.stringify()` を適用した模範例です。

```js
// JSON の一例を作成
var session = {
  screens: [],
  state: true,
};
session.screens.push({ name: "screenA", width: 450, height: 250 });
session.screens.push({ name: "screenB", width: 650, height: 350 });
session.screens.push({ name: "screenC", width: 750, height: 120 });
session.screens.push({ name: "screenD", width: 250, height: 60 });
session.screens.push({ name: "screenE", width: 390, height: 120 });
session.screens.push({ name: "screenF", width: 1240, height: 650 });

// JSON.stringify() で JSON 文字列に変換してから
// session の名前で localStorage に保存
localStorage.setItem("session", JSON.stringify(session));

// JSON.stringify() で生成されて localStorage に保存された文字列を
// 再び JSON オブジェクトに変換する方法の例
var restoredSession = JSON.parse(localStorage.getItem("session"));

// ここで変数 restoredSession には localStorage に保存されていた
// オブジェクトが入っている
console.log(restoredSession);
```

### Well-formed JSON.stringify()

well-formed JSON.stringify 仕様を実装しているエンジンは、サロゲート文字、U+D800 から U+DFFF までのすべてのコードポイントを、リテラルではなく Unicode エスケープシーケンスを使用して文字列化します。この変更前は、入力にサロゲート文字が含まれている場合、`JSON.stringify` はサロゲート文字をそのまま出力していました。このような文字列は妥当な UTF-8 または UTF-16 でエンコードされていませんでした。

```js
JSON.stringify("\uD800"); // '"�"'
```

しかし、この変更で `JSON.stringify` は lone surrogates を JSON エスケープシーケンスによって表すようになり、妥当な UTF-8 または UTF-16 でエンコードすることができるようになりました。

```js
JSON.stringify("\uD800"); // '"\\ud800"'
```

この変更では、サロゲート文字の Unicode エスケープをサロゲート文字と同一のものとして扱うため、 `JSON.stringify` の結果を、JSON テキストを妥当である限りどのようなものでも受け付ける `JSON.parse` のような API に渡したときに後方互換性があります。`JSON.stringify` の結果を直接解析する場合*のみ*、`JSON.stringify` がこれらのコードポイントに対して 2 通りのエンコーディングをする可能性があることに注意して扱う必要があります。

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-json.stringify |

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

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

関連情報
----

* `core-js` による現在の `JSON.stringify` の挙動 (シンボルおよび well-formed unicode) のポリフィル
* `JSON.parse()`
* cycle.js – `JSON.decycle` と `JSON.retrocycle` の 2 つの関数を導入します。これらは循環的な構造と DAG を、拡張されたレトロ互換性のある JSON 形式にエンコードおよびデコードすることができます。


Set.prototype.keys() - JavaScript

Set.prototype.keys()
====================

**`keys()`** は `Set` インターフェイスのメソッドで、 `values()` メソッドの別名です。

構文
--

```js
keys()
```

### 引数

なし。

### 返値

新しい反復可能なイテレーターオブジェクトです。

例
-

### keys() の使用

`keys()` メソッドは `values()` メソッドとまったく同じです。

```js
const mySet = new Set();
mySet.add("foo");
mySet.add("bar");
mySet.add("baz");

const setIter = mySet.keys();

console.log(setIter.next().value); // "foo"
console.log(setIter.next().value); // "bar"
console.log(setIter.next().value); // "baz"
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-set.prototype.keys |

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

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

関連情報
----

* `Set.prototype.entries()`
* `Set.prototype.values()`


Set[@@species] - JavaScript

Set[@@species]
==============

**`Set[@@species]`** アクセサープロパティは、`Set` オブジェクトのコピー方法を指定する未使用のアクセッサープロパティです。

構文
--

```js
Set[Symbol.species]
```

### 返値

`get @@species` が呼び出されたコンストラクター (`this`) の値です。この返値は、コピーされた `Set` インスタンスを生成するために使用されます。

解説
--

`@@species` アクセサープロパティは、 `Set` オブジェクトの既定のコンストラクターを返します。サブクラスのコンストラクターはコンストラクターに代入することで、これをオーバーライドすることができます。

**メモ:** このプロパティは現在、 `Set` のどのメソッドでも使用されていません。

例
-

### 通常のオブジェクトの species

`@@species` プロパティは、既定のコンストラクター関数、すなわち `Set` の `Set` コンストラクターを返します。

```js
Set[Symbol.species]; // Set() 関数
```

### 派生オブジェクトの species

独自の `Set` のサブクラス、例えば `MySet` のインスタンス内では、 `MySet` の species は `MySet` コンストラクターです。しかし、派生クラスのメソッドで、親である `Set` オブジェクトを返すためにこれをオーバーライドしたいかもしれません。

```js
class MySet extends Set {
  // MySet species を親である Set コンストラクターにオーバーライド。
  static get [Symbol.species]() {
    return Set;
  }
}
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-get-set-@@species |

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

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

関連情報
----

* `Set`
* `Symbol.species`


Set.prototype.size - JavaScript

Set.prototype.size
==================

**`size`** は `Set` インスタンスのアクセサープロパティで、この集合内の（固有の）要素の数を返します。

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

解説
--

`size` の値は、`Set` オブジェクトがいくつの要素を持つかを表す整数値です。`size` に対するセットアクセサー関数は `undefined` です。よって、このプロパティは変更できません。

例
-

### size の使用

```js
const mySet = new Set();
mySet.add(1);
mySet.add(5);
mySet.add("some text");

console.log(mySet.size); // 3
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-get-set.prototype.size |

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

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

関連情報
----

* `Set`


Set.prototype[@@iterator]() - JavaScript

Set.prototype[@@iterator]()
===========================

**`[@@iterator]()`** は `Set` インスタンスのメソッドで、反復処理プロトコルを実装しており、 `Set` オブジェクトを、反復可能オブジェクトを期待するほとんどの構文、例えばスプレッド構文 や `for...of` ループなどで利用できるようにします。これは、挿入順に集合の値を返す集合イテレーターオブジェクトを返します。

**`@@iterator`** プロパティの初期値は `Set.prototype.values` プロパティの初期値と同じ関数オブジェクトです。

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

構文
--

```js
set[Symbol.iterator]()
```

### 引数

なし。

### 返値

`Set.prototype.values()` と同じく、値の集合を生成する新しい反復可能なイテレーターオブジェクトを返します。

例
-

### for...of ループを使用した反復処理

このメソッドを直接呼び出す必要はほとんどないことに注意してください。`@@iterator` メソッドの存在によって `Set` オブジェクトは反復可能になり、`for...of` 文のような反復処理の構文は自動的にこのメソッドを呼ぶことで反復処理を行うためのイテレーターを取得できるようになります。

```js
const mySet = new Set();
mySet.add("0");
mySet.add(1);
mySet.add({});

for (const v of mySet) {
  console.log(v);
}
```

### 手動でイテレーターを扱う

反復処理を最大限に制御するために、返されたイテレーターオブジェクトの `next()` メソッドを手動で呼び出すことも可能です。

```js
const mySet = new Set();
mySet.add("0");
mySet.add(1);
mySet.add({});

const setIter = mySet[Symbol.iterator]();

console.log(setIter.next().value); // "0"
console.log(setIter.next().value); // 1
console.log(setIter.next().value); // Object
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-set.prototype-@@iterator |

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

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

関連情報
----

* `Set`
* `Set.prototype.entries()`
* `Set.prototype.keys()`
* `Set.prototype.values()`
* `Symbol.iterator`
* 反復可能プロトコル


Set.prototype.values() - JavaScript

Set.prototype.values()
======================

**`values()`** は `Set` インターフェイスのメソッドで、集合の新しいイテレーターオブジェクトを返します。これはこの集合のそれぞれの要素をの値を挿入順に返します。

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

構文
--

```js
values()
```

### 引数

なし。

### 返値

新しい反復可能なイテレーターオブジェクトです。

例
-

### values() の使用

```js
const mySet = new Set();
mySet.add("foo");
mySet.add("bar");
mySet.add("baz");

const setIter = mySet.values();

console.log(setIter.next().value); // "foo"
console.log(setIter.next().value); // "bar"
console.log(setIter.next().value); // "baz"
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-set.prototype.values |

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

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

関連情報
----

* `Set.prototype.entries()`
* `Set.prototype.keys()`


Set() コンストラクター - JavaScript

Set() コンストラクター
==============

**`Set()`** コンストラクターは `Set` オブジェクトを生成します。

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

構文
--

```js
new Set()
new Set(iterable)
```

**メモ:** `Set()` は `new` を付けてのみ構築することができ案す。 `new` 無しで呼び出そうとすると `TypeError` が発生します。

### 引数

`iterable` 省略可

反復可能オブジェクトが渡された場合は、そのすべての要素が新しい `Set` に加えられます。

この引数を指定しなかった場合、または値が `null` だった場合、新しい `Set` は空になります。

### 返値

新しい `Set` オブジェクトです。

例
-

### `Set` オブジェクトの使用

```js
const mySet = new Set();

mySet.add(1); // Set [ 1 ]
mySet.add(5); // Set [ 1, 5 ]
mySet.add(5); // Set [ 1, 5 ]
mySet.add("some text"); // Set [ 1, 5, 'some text' ]
const o = { a: 1, b: 2 };
mySet.add(o);
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-set-constructor |

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

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

関連情報
----

* `Set` のポリフィル (`core-js`)
* `Set`


Set.prototype.entries() - JavaScript

Set.prototype.entries()
=======================

**`entries()`** は `Set` インターフェイスのメソッドで、集合の新しいイテレーターオブジェクトを返します。これは **`[value, value]` の配列**の形で集合の各要素を挿入順に返します。 `Set` オブジェクトは、`Map` オブジェクトのように `key` を持つことはありません。しかしながら、`Map` オブジェクトと似た API をもつために、それぞれの項目は *key* と *value* に対して同じ値を持ちます。そのため、配列 `[value, value]` が返されます。

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

構文
--

```js
entries()
```

### 引数

なし。

### 返値

新しい反復可能なイテレーターオブジェクトです。

例
-

### entries() の使用

```js
const mySet = new Set();
mySet.add("foobar");
mySet.add(1);
mySet.add("baz");

const setIter = mySet.entries();

console.log(setIter.next().value); // ["foobar", "foobar"]
console.log(setIter.next().value); // [1, 1]
console.log(setIter.next().value); // ["baz", "baz"]
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-set.prototype.entries |

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

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

関連情報
----

* `Set.prototype.keys()`
* `Set.prototype.values()`


Set.prototype.has() - JavaScript

Set.prototype.has()
===================

**`has()`** は `Set` インターフェイスのメソッドで、指定された値をもつ要素がこの集合内に存在するかどうかを示す論理値を返します。

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

構文
--

```js
has(value)
```

### 引数

`value`

この `Set` オブジェクトに存在するかを検査する値です。

### 返値

この `Set` オブジェクト内に指定された値をもつ要素が存在していたら `true` を返します。さもなければ `false` を返します。

例
-

### has() メソッドの使用

```js
const mySet = new Set();
mySet.add("foo");

console.log(mySet.has("foo")); // true
console.log(mySet.has("bar")); // false

const set1 = new Set();
const obj1 = { key1: 1 };
set1.add(obj1);

console.log(set1.has(obj1)); // true
console.log(set1.has({ key1: 1 })); // オブジェクト参照が異なるため false を返す
console.log(set1.add({ key1: 1 })); // set1 には 2 つの項目が含まれるようになる
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-set.prototype.has |

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

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

関連情報
----

* `Set`
* `Set.prototype.add()`
* `Set.prototype.delete()`


Set.prototype.add() - JavaScript

Set.prototype.add()
===================

**`add()`** は `Set` インスタンスのメソッドで、この集合に同じ値を持つ要素がない場合、指定した値を持つ新しい要素をこの集合に追加します。

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

構文
--

```js
add(value)
```

### 引数

`value`

`Set` オブジェクトに追加する要素の値です。

### 返値

追加された値を持つ `Set` オブジェクトです。

例
-

### add() メソッドの使用

```js
const mySet = new Set();

mySet.add(1);
mySet.add(5).add("some text"); // 連鎖可能

console.log(mySet);
// Set [1, 5, "some text"]
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-set.prototype.add |

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

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

関連情報
----

* `Set`
* `Set.prototype.delete()`
* `Set.prototype.has()`


Set.prototype.clear() - JavaScript

Set.prototype.clear()
=====================

**`clear()`** は `Set` インターフェイスのメソッドで、この集合からすべての要素を取り除きます。

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

構文
--

```js
clear()
```

### 引数

なし。

### 返値

なし (`undefined`)。

例
-

### clear() メソッドの使用

```js
const mySet = new Set();
mySet.add(1);
mySet.add("foo");

console.log(mySet.size); // 2
console.log(mySet.has("foo")); // true

mySet.clear();

console.log(mySet.size); // 0
console.log(mySet.has("bar")); // false
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-set.prototype.clear |

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

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

関連情報
----

* `Set`
* `Set.prototype.delete()`


Set.prototype.delete() - JavaScript

Set.prototype.delete()
======================

**`delete()`** は `Set` インターフェイスのメソッドで、指定された値がこの集合にあれば、取り除きます。

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

構文
--

```js
setInstance.delete(value)
```

### 引数

`value`

`Set` から取り除く要素の値です。

### 返値

`true` ならば `value` が既に `Set` に存在していたことを表します。そうでなければ `false` を返します。

例
-

### delete() メソッドの使用

```js
const mySet = new Set();
mySet.add("foo");

mySet.delete("bar"); // 削除するべき要素が見つからなければ false を返す
mySet.delete("foo"); // 正常に要素を削除出来れば true を返す

mySet.has("foo"); // 存在しない要素を確認すると false を返す
```

### Set からオブジェクトを削除する

オブジェクト同士は参照で比較されるため、元のオブジェクトへの参照を保持していない場合は、個々のプロパティをチェックして削除する必要があります。

```js
const setObj = new Set(); // 新しいセットを作成

setObj.add({ x: 10, y: 20 }); // セットにオブジェクトを追加

setObj.add({ x: 20, y: 30 }); // セットにオブジェクトを追加

// `x > 10` のポイントを削除
setObj.forEach((point) => {
  if (point.x > 10) {
    setObj.delete(point);
  }
});
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-set.prototype.delete |

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

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

関連情報
----

* `Set`
* `Set.prototype.clear()`


Set.prototype.forEach() - JavaScript

Set.prototype.forEach()
=======================

**`forEach()`** は `Set` インターフェイスのメソッドで、指定された関数をこの集合のそれぞれの値に対して一回ずつ、挿入順で実行します。

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

構文
--

```js
forEach(callbackFn)
forEach(callbackFn, thisArg)
```

### 引数

`callback`

この集合のそれぞれの項目に対して実行する関数です。この関数は次の引数で呼び出されます。

`value`

それぞれの反復処理の値です。

`key`

それぞれの反復処理のキーです。これは常に `value` と同じです。

`set`

反復処理が行われる集合です。

`thisArg` 省略可

`callbackFn` を実行するときｎ、`this` として使用する値です。

### 返値

`undefined` です。

解説
--

`forEach()` メソッドは、この `Set` オブジェクトに実際に存在するそれぞれの値に対して、指定された `callback` を一回ずつ実行します。削除された値に対しては呼び出しません。ただし、`undefined` の値をもつ要素に対しては実行します。

`callback` は **3 つの引数**で呼び出されます。

* この**要素の値**
* この**要素のキー**
* **走査を行っている `Set` オブジェクト**

しかし、 `Set` オブジェクトにキーがないので、最初の 2 つの引数は、両方とも `Set` に含まれる**値**です。これにより、他の `Map` や `Array` の `forEach()` メソッドと整合が取れています。

`thisArg` 引数が `forEach()` に渡された場合、 `callback` を呼び出すときにこれが渡され、 `this` 値として使用されます。渡されなかった場合は、さもなければ、`this` 値として使用するために `undefined` 値が渡されます。 `this` の値が最終的に `callback` から見える姿は、関数から見た `this` を決定するための通常のルールに応じて決まります。

それぞれの値は 1 回ずつ処理されますが、 `forEach()` が終了する前に削除・再追加された場合は例外です。処理される前に削除された値に対しては `callback` は実行されません。 `forEach()` が終了する前に追加された新しい値は処理されます。

`forEach()` は `callback` 関数を `Set` オブジェクト内のそれぞれの要素に対して一回ずつ実行します。返値はありません。

例
-

### Set オブジェクトの内容を出力する

次のコードでは、`Set` オブジェクト内の各要素に対してログを出力します。

```js
function logSetElements(value1, value2, set) {
  console.log(`s[${value1}] = ${value2}`);
}

new Set(["foo", "bar", undefined]).forEach(logSetElements);

// Logs:
// "s[foo] = foo"
// "s[bar] = bar"
// "s[undefined] = undefined"
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-set.prototype.foreach |

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

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

関連情報
----

* `Array.prototype.forEach()`
* `Map.prototype.forEach()`


let - JavaScript

let
===

**`let`** 文はブロックスコープのローカル変数を宣言します。任意で値を代入して初期化できます。

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

構文
--

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

### 引数

`nameN`

宣言する変数または複数の変数の名前です。それぞれは JavaScript の正式な識別子である必要があります。

`valueN` 省略可

宣言される変数ごとに、任意で初期値を JavaScript の正式な式で指定することができます。

分割代入構文を変数の宣言に使用することもできます。

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

解説
--

`let` を使用することで、それが使用されたブロックの文または式にスコープを限定した変数を宣言することができます。これは `var` キーワードのように、変数をブロックスコープに関係なく、グローバルや関数全体のローカルに定義するようなことはありません。他にも `var` と `let` の違いは、後者が宣言文に到達した後でしかアクセスできないという点があります（一時的なデッドゾーンを参照）。このため、`let` 宣言は一般に巻き上げされないと見なされています。

`const` と同様に、`let` はグローバル (一番上のスコープ) で宣言されたときに `window` オブジェクトのプロパティを生成*しません*。

なぜ "let" という名前が選ばれたのかについての説明は、リンク先の StackOverflow の解答で解説されています。

`let` 変数の多くの課題は、使用されるスコープの先頭で宣言することで避けることができます（そうすることで、読み取り可能な範囲に影響を与えることがあります）。

`var` とは異なり、`let` は宣言であり、文ではないものです。つまり、単独の `let` 宣言をブロックの本体として使用することはできません（変数にアクセスする方法がないので、明らかです）。

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

例
-

### スコープのルール

`let` で定義された変数は、自身が定義されたブロックと、そこに含まれるサブブロックがスコープになります。この点において `let` のふるまいは `var` にとてもよく似ています。大きな違いは、`var` で定義された変数のスコープはそれを含んでいる関数全体になるということです。

```js
function varTest() {
  var x = 1;
  {
    var x = 2; // 同じ変数です!
    console.log(x); // 2
  }
  console.log(x); // 2
}

function letTest() {
  let x = 1;
  {
    let x = 2; // 異なる変数
    console.log(x); // 2
  }
  console.log(x); // 1
}
```

プログラムや関数の最上位においては、`let` は `var` とは異なり、グローバルオブジェクト上にプロパティを生成しません。例を示します。

```js
var x = "global";
let y = "global";
console.log(this.x); // "global"
console.log(this.y); // undefined
```

### 再宣言

同じ関数やブロックのスコープ内で同じ変数を再宣言すると `SyntaxError` が発生します。

```js
if (x) {
  let foo;
  let foo; // SyntaxError が発生します。
}
```

`switch` 文には 1 つのブロックしかないため、エラーが発生してしまうかもしれません。

```js
let x = 1;

switch (x) {
  case 0:
    let foo;
    break;
  case 1:
    let foo; // 再宣言のため TypeError
    break;
}
```

ただし、指摘しておくべき重要な点として、case 節の中で入れ子にしたブロックを使えば、新しいブロックスコープの字句環境を作ることができるため、上記のような再宣言エラーが発生しなくなります。

```js
let x = 1;

switch (x) {
  case 0: {
    let foo;
    break;
  }
  case 1: {
    let foo;
    break;
  }
}
```

Firefox のウェブコンソール（**ツール** > **ウェブ開発者ツール** > **ウェブコンソール**）などの REPL で実験しているときに、同じ名前の `let` 宣言を 2 つの入力で実行すると、同じ再宣言エラーが得られる場合があります。この課題については、Firefox bug 1580891でさらなるディスカッションをご覧ください。Chrome コンソールでは、異なる REPL 入力間で `let` を再宣言することができます。

### 一時的なデッドゾーン (TDZ)

`let` または `const` 変数は、ブロックの始まりからコードが実行されて変数が宣言され初期化される行に到達するまでは、「一時的なデッドゾーン」(TDZ) 内にあると言います。

TDZ の中にいる間は、変数は値で初期化されておらず、何かアクセスしようとすると `ReferenceError` が発生することになります。変数は、宣言されたコードの行まで実行されると、値で初期化されます。変数宣言で初期値を指定しなかった場合は、`undefined`という値で初期化されます。

`var` で宣言された変数が `undefined` の値で始まるのとは異なり、これらの変数は定義が評価されるまでは初期化されません。以下のコードは、`let` と `var` が宣言された行より前のコードでアクセスされた場合に、異なる結果が得られることを示しています。

```js
{
  // TDZ starts at beginning of scope
  console.log(bar); // undefined
  console.log(foo); // ReferenceError
  var bar = 1;
  let foo = 2; // End of TDZ (for foo)
}
```

コードが書かれた順番（位置）ではなく、実行の順番（時間）に依存するゾーンであるため、「時間的」という言葉が使用されています。例えば、下記のコードは、`let` 変数を使用する関数は変数宣言の前に現れていますが、その関数が TDZ の外で呼び出されているため、動作します。

```js
{
  // TDZ はスコープの先頭から始まる
  const func = () => console.log(letVar); // OK

  // TDZ の中では、letVar にアクセスすると `ReferenceError` が発生する

  let letVar = 3; // TDZ の終わり (letVar)
  func(); // TDZ の外での呼び出し
}
```

#### 一時的なデッドゾーンと typeof

`typeof` 演算子を使用して一時的なデッドゾーン内の変数の型を確認するしようとすると、`ReferenceError` が発生します。

```js
// 'ReferenceError' が発生します
console.log(typeof i);
let i = 10;
```

これは、宣言されていない変数に対して `typeof` を使用した場合、`undefined` の値と見なされるのとは異なります。

```js
// 'undefined' と表示
console.log(typeof undeclaredVariable);
```

#### 一時的なデッドゾーンと字句スコープと組み合わせた例

このブロックの `foo` は一時的なデッドゾーンの中にあります。

```js
function test() {
  var foo = 33;
  if (foo) {
    let foo = foo + 55; // ReferenceError
  }
}
test();
```

 外側の `var foo` に値があるため、`if` ブロックは実行されます。
 しかし、字句スコープにより、この値はブロックの内部では利用できません。`if`ブロックの内側にある識別子 `foo` は `let foo` になります。
 式 `foo + 55` で `ReferenceError` が発生します。これは `let foo` の初期化がまだ完了していない、つまり一時的なデッドゾーンにあるためです。

 この現象は、以下のような状況で混乱することがあります。
 `let n of n.a` という命令は、すでに for ループのブロックのプライベートスコープ内にあります。
 そのため、識別子 `n.a` は、命令自体の最初の部分 (`let n`) にある '`n`' オブジェクトのプロパティ '`a`' として解決されます。その宣言文にはまだ到達・完了していないため、まだ一時的なデッドゾーン内にあるとみなされます。

```js
function go(n) {
  // n here is defined!
  console.log(n); // { a: [1, 2, 3] }

  for (let n of n.a) {
    // ^ ReferenceError
    console.log(n);
  }
}

go({ a: [1, 2, 3] });
```

### そのほかの場面

ブロックの中で使えば、`let` の変数のスコープはそのブロックの中に制限されます。スコープが自身の宣言された関数全体になる `var` との違いに注意してください。

```js
var a = 1;
var b = 2;

{
  var a = 11; // スコープはグローバル
  let b = 22; // スコープは if ブロック内

  console.log(a); // 11
  console.log(b); // 22
}

console.log(a); // 11
console.log(b); // 2
```

しかし、下記の `var` と `let` 宣言の組み合わせは、`var` がブロックの先頭に配置されているため、`SyntaxError` になります。これによって、変数が暗黙的に再宣言されるからです。

```js
let x = 1;

{
  var x = 2; // 再宣言のため SyntaxError
}
```

仕様書
---

| 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`
* `const`
* 巻き上げ
* ES6 In Depth: `let` and `const`
* Breaking changes in `let` and `const` in Firefox 44
* You Don't Know JS: Scope & Closures: Chapter 3: Function vs. Block Scope
* StackOverflow: What is the Temporal Dead Zone?
* StackOverflow: What is the difference between using `let` and `var`?


async function - JavaScript

async function
==============

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

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

* Learn more
* See full compatibility
* Report feedback
**`async function`** 宣言は非同期関数を宣言し、その中で `await` キーワードを使うことができます。`async` および `await` キーワードを使用することで、プロミスベースの非同期の動作を、プロミスチェーンを明示的に構成する必要なく、よりすっきりとした方法で書くことができます。

非同期関数は式としても定義することができます。

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

構文
--

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

### 引数

`name`

関数の名前です。

`param` 省略可

関数に渡す引数の名前です。

`statements` 省略可

関数の本体を構成する文です。`await` の仕組みを使用することができます。

### 返値

`Promise` で、非同期関数から返される値で解決するか、または非同期関数内で捕捉されなかった例外で拒否されます。

解説
--

非同期関数には、 `await` 式を置くことができます。 await 式は返されたプロミスが履行されるか拒否されるまで実行を中断することで、プロミスを返す関数をあたかも同期しているかのように動作させます。プロミスの解決済みの値は、await 式の返値として扱われます。`async` と `await` を使用すると、非同期コードに通常の `try` / `catch` ブロックを使用することができます。

**メモ:** キーワード `await` は、通常の JavaScript コード内の非同期関数内でのみ有効です。非同期関数の外で使用した場合は `SyntaxError` が発生します。

`await` は JavaScript モジュールでは単独で使用することができます。

**メモ:** `async`/`await` の目的は、プロミスベースの API を利用するのに必要な構文を簡素化することです。 `async`/`await` の動作は、ジェネレーターとプロミスの組み合わせに似ています。

非同期関数は常にプロミスを返します。非同期関数の返値が明示的にプロミスでない場合は、暗黙的にプロミスでラップされます。

例えば、以下のコードを考えてください。

```js
async function foo() {
  return 1;
}
```

これは、次のコードに似ています。

```js
function foo() {
  return Promise.resolve(1);
}
```

**メモ:**

非同期関数の返値が `Promise.resolve` にラップされているかのように動作するとしても、両者は同等ではありません。

与えられた値がプロミスであった場合、 `Promise.resolve` は同じ参照を返すのに対し、非同期関数は異なる*参照*を返します。

これは、あるプロミスと非同期関数の返値が等しいかどうかをチェックする場合に問題になることがあります。

```js
const p = new Promise((res, rej) => {
  res(1);
});

async function asyncReturn() {
  return p;
}

function basicReturn() {
  return Promise.resolve(p);
}

console.log(p === basicReturn()); // true
console.log(p === asyncReturn()); // false
```

非同期関数の本体は、 await 式で分割されていると考えることができます。最上位のコードは、 (ある場合) 最初の await 式まで、それを含めて同期的に実行されます。したがって、await 式のない非同期関数は同期的に実行されます。しかし、関数本体の中に await 式がある場合、非同期関数は常に非同期に完了します。

例:

```js
async function foo() {
  await 1;
}
```

これは次のものと等価です。

```js
function foo() {
  return Promise.resolve(1).then(() => undefined);
}
```

それぞれの await 式の後のコードは、`.then` コールバックの中に存在すると考えることができます。このようにして、関数を再帰的に実行するたびに、プロミスチェーンが徐々に構築されていきます。返値はチェーンの最後のリンクになります。

次の例では、 2 つのプロミスを連続して待ち受けます。関数 `foo` の処理は 3 段階に分かれています。

1. 関数 foo の本体の最初の行は、保留中のプロミスで await 式が構成された状態で、同期的に実行されます。その後、`foo` の処理は中断され、`foo` を呼び出した関数に制御が返されます。
2. しばらくして、最初のプロミスが履行されるか拒否されると、制御は `foo` に戻ります。（拒否されなかった場合は）最初のプロミスが履行された結果が await 式から返されます。ここでは `1` が `result1` に代入されます。処理は続き、2 つ目の await 式が評価されます。このときも `foo` の処理が中断され、制御が移譲されます。
3. しばらくして、2 つ目のプロミスが履行されたか拒否されたとき、制御は `foo` に再び入ります。2 つ目のプロミスが解決した結果が 2 番目の await 式から返されます。ここでは `2` が `result2` に代入されます。制御は（もしあれば）return 式に移ります。既定の返値である `undefined` が、現在のプロミスの解決値として返されます。

```js
async function foo() {
  const result1 = await new Promise((resolve) =>
    setTimeout(() => resolve("1")),
  );
  const result2 = await new Promise((resolve) =>
    setTimeout(() => resolve("2")),
  );
}
foo();
```

プロミスチェーンが一度に構築されないことに注意してください。プロミスチェーンは、非同期関数に制御を渡したり戻したりしながら、段階的に構築されていきます。そのため、同時並行の非同期処理を行う際には、エラー処理の動作に注意しなければなりません。

例えば、以下のコードでは、プロミスチェーンの先に `.catch` ハンドラーが設定されていたとしても、未処理のプロミス拒否エラーが発生します。これは、`p1` から制御が戻るまで、`p2` がプロミスチェーンに「配線」されないためです。

```js
async function foo() {
  const p1 = new Promise((resolve) => setTimeout(() => resolve("1"), 1000));
  const p2 = new Promise((\_, reject) => setTimeout(() => reject("2"), 500));
  const results = [await p1, await p2]; // こうしないでください。 Promise.all または Promise.allSettled を使用してください。
}
foo().catch(() => {}); // すべてのエラーを浅くしようとする...
```

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

例
-

### 非同期関数と実行順

```js
function resolveAfter2Seconds() {
  console.log("starting slow promise");
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve("slow");
      console.log("slow promise is done");
    }, 2000);
  });
}

function resolveAfter1Second() {
  console.log("starting fast promise");
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve("fast");
      console.log("fast promise is done");
    }, 1000);
  });
}

async function sequentialStart() {
  console.log("==SEQUENTIAL START==");

  // 1. これは即時実行される
  const slow = await resolveAfter2Seconds();
  console.log(slow); // 2. これは 1. の 2 秒後に実行される

  const fast = await resolveAfter1Second();
  console.log(fast); // 3. これは 1. の 3 秒後に実行される
}

async function concurrentStart() {
  console.log("==CONCURRENT START with await==");
  const slow = resolveAfter2Seconds(); // ただちにタイマーを起動
  const fast = resolveAfter1Second(); // ただちにタイマーを起動

  // 1. これは即時実行される
  console.log(await slow); // 2. これは 1. の 2 秒後に実行される
  console.log(await fast); // 3. fast はすでに解決しているので、これは 1. の 2 秒後 (2.の直後) に実行される
}

function concurrentPromise() {
  console.log("==CONCURRENT START with Promise.all==");
  return Promise.all([resolveAfter2Seconds(), resolveAfter1Second()]).then(
    (messages) => {
      console.log(messages[0]); // slow
      console.log(messages[1]); // fast
    },
  );
}

async function parallel() {
  console.log("==PARALLEL with await Promise.all==");

  // 2 つの jobs を並列に実行し両方が完了するのを待つ
  await Promise.all([
    (async () => console.log(await resolveAfter2Seconds()))(),
    (async () => console.log(await resolveAfter1Second()))(),
  ]);
}

sequentialStart(); // 2 秒後に "slow" をログ出力し、その 1 秒後に "fast" をログ出力する

// 直前の処理を待つ
setTimeout(concurrentStart, 4000); // 2 秒後に "slow" と "fast" をログ出力する

// 直前の処理を待つ
setTimeout(concurrentPromise, 7000); // concurrentStart と同様

// 直前の処理を待つ
setTimeout(parallel, 10000); // 本当に並列処理となるため 1 秒後に "fast" とログ出力し、その 1 秒後に "slow" とログ出力する
```

#### await と並列性

`sequentialStart` では、最初の `await` のために実行が 2 秒間待機し、 2 つ目の `await` のためにさらに 1 秒間待機します。 2 つ目のタイマーは最初のタイマーが起動している間は作成されません。コードは 3 秒後に終了します。

`concurrentStart` では、両方のタイマーが作成され、両方とも `await` される、すなわち待機させられます。タイマーは同時に実行されているため、 3 秒後ではなく 2 秒後に、すなわち最も遅いタイマーにあわせて終了します。
 しかし、 `await` の呼び出しは依然として逐次処理であり、これは 2 つ目の `await` が 1 つ目の終了まで待つことを意味します。このケースでは、最も速いタイマーが最も遅いタイマーのあとに処理されることになります。

 複数の処理を安全に並列に実行したい場合は、 `Promise.all` または
 `Promise.allSettled` の呼び出しで待つ必要があります。

**警告:** 関数 `concurrentStart` と `concurrentPromise` は機能的に同等ではありません。

`concurrentStart` では、プロミス `fast` がプロミス `slow` の履行よりも前に拒否された場合、呼び出し元が catch 節を構成しているかどうかにかかわらず、プロミスの拒否が処理されないというエラーが発生します。

`concurrentPromise` では、`Promise.all` がプロミスチェーンを一括して配線します。つまり、操作はプロミスの拒否の順番に関係なくすばやく失敗し、エラーは構成されたプロミスチェーン内で常に発生するため、通常の方法で捕捉することができます。

### プロミスチェーンを非同期関数で書き換える

`Promise` を返す API はプロミスチェーンを返し、関数を複数の部品に分割できます。次のコードを想定してください。

```js
function getProcessedData(url) {
  return downloadData(url) // プロミスを返す
    .catch((e) => downloadFallbackData(url)) // プロミスを返す
    .then((v) => processDataInWorker(v)); // プロミスを返す
}
```

次のように 1 つの非同期関数に書き換えることができます。

```js
async function getProcessedData(url) {
  let v;
  try {
    v = await downloadData(url);
  } catch (e) {
    v = await downloadFallbackData(url);
  }
  return processDataInWorker(v);
}
```

他にも、 `catch()` によってプロミスを連鎖させることができます。

```js
async function getProcessedData(url) {
  const v = await downloadData(url).catch((e) => downloadFallbackData(url));
  return processDataInWorker(v);
}
```

二番目の例では、有効であるにもかかわらず、 `await` 文が `return` キーワードの後にないことに注意してください。非同期関数の返値は、（この例のように）既にプロミスでない限り、暗黙的に `Promise.resolve` でラップされるからです。

仕様書
---

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

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

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

関連情報
----

* 非同期関数式
* `AsyncFunction` オブジェクト
* `await`
* Decorating Async JavaScript Functions (*innolitics.com*)


throw - JavaScript

throw
=====

**`throw`** 文は、ユーザー定義の例外を発生させます。
 現在の関数の実行を停止し（`throw` の後の文は実行されません）、コールスタック内の最初の `catch` ブロックに制御を移します。呼び出し元の関数に `catch` ブロックが存在しない場合は、プログラムが終了します。

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

構文
--

```js
throw expression;
```

`expression`

発生させる例外の式です。

解説
--

`throw` 文を使用して例外を発生させることができます。例外を発生させるときは、 `expression` で例外の値を指定します。以下のいずれもが例外を発生させます。

```js
throw "Error2"; // 文字列値である例外を生成します
throw 42; // 値 42 である例外を生成します
throw true; // 値 true である例外を生成します
throw new Error("Required"); // Required というメッセージを持ったエラーオブジェクトを生成します
```

また、`throw` 文は自動セミコロン挿入 (ASI)の影響を受けることに注意してください。`throw` キーワードと式の間に改行は許されていません。

例
-

### オブジェクトで例外を発生させる

例外を派生させるときにオブジェクトを指定することができます。そうすれば、 `catch` ブロックの中でそのオブジェクトのプロパティを参照できます。次の例は、 `UserException` 型のオブジェクトを生成し、それを `throw` 文の中で使っています。

```js
function UserException(message) {
  this.message = message;
  this.name = "UserException";
}
function getMonthName(mo) {
  mo--; // 配列の添字のために月の数を調整する (1 = Jan, 12 = Dec)
  const months = [
    "Jan",
    "Feb",
    "Mar",
    "Apr",
    "May",
    "Jun",
    "Jul",
    "Aug",
    "Sep",
    "Oct",
    "Nov",
    "Dec",
  ];
  if (months[mo] !== undefined) {
    return months[mo];
  } else {
    throw new UserException("InvalidMonthNo");
  }
}

let monthName;

try {
  // 試みる文
  const myMonth = 15; // 15 は範囲外であり、例外が発生する
  monthName = getMonthName(myMonth);
} catch (e) {
  monthName = "unknown";
  console.error(e.message, e.name); // エラーハンドラーに例外オブジェクトを渡す
}
```

### オブジェクトで例外を発生させる他の例

次の例では入力文字列でアメリカの郵便番号であるかどうかをテストします。郵便番号が無効な書式を使っていた場合は、 throw 文で `ZipCodeFormatException` 型のオブジェクトを生成して例外を発生させます。

```js
/\*
 \* ZipCode オブジェクトを生成します。
 \*
 \* 郵便番号として受け入れられる書式は次のとおりです。
 \* 12345
 \* 12345-6789
 \* 123456789
 \* 12345 6789
 \*
 \* もし ZipCode コンストラクターに渡された引数が、これらのパターンの
 \* うちのどれにも一致しないのであれば、例外が発生します。
 \*/
class ZipCode {
  static pattern = /[0-9]{5}([- ]?[0-9]{4})?/;
  constructor(zip) {
    zip = String(zip);
    const match = zip.match(ZipCode.pattern);
    if (!match) {
      throw new ZipCodeFormatException(zip);
    }
    // 郵便番号の値は文字列中で最初に一致した部分です。
    this.value = match[0];
  }
  valueOf() {
    return this.value;
  }
  toString() {
    return this.value;
  }
}

class ZipCodeFormatException extends Error {
  constructor(zip) {
    super(`${zip} does not conform to the expected format for a zip code`);
  }
}

/\*
 \* これは、US の住所のためのアドレスデータを検証するスクリプトで
 \* 使われるかもしれません。
 \*/

const ZIPCODE\_INVALID = -1;
const ZIPCODE\_UNKNOWN\_ERROR = -2;

function verifyZipCode(z) {
  try {
    z = new ZipCode(z);
  } catch (e) {
    const isInvalidCode = e instanceof ZipCodeFormatException;
    return isInvalidCode ? ZIPCODE\_INVALID : ZIPCODE\_UNKNOWN\_ERROR;
  }
  return z;
}

a = verifyZipCode(95060); // 95060 を返します
b = verifyZipCode(9560); // -1 を返します
c = verifyZipCode("a"); // -1 を返します
d = verifyZipCode("95060"); // 95060 を返します
e = verifyZipCode("95060 1234"); // 95060 1234 を返します
```

### 例外を再発生させる

例外を捕捉した後、その例外を再度発生させるために `throw` を使うことができます。次の例では、数値である例外を捕捉し、もしその値が 50 を超えるのなら、それを改めて発生させます。改めて発生した例外は、利用者がわかるように、囲んでいる関数または最上位にいたるまで伝播します。

```js
try {
  throw n; // 数値である例外を発生させる
} catch (e) {
  if (e <= 50) {
    // 1 から 50 の例外を操作するための文
  } else {
    // この例外を操作できないので、再度発生させる
    throw e;
  }
}
```

仕様書
---

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

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

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

関連情報
----

* `try...catch`
* `Error`


export - JavaScript

export
======

**`export`** 宣言は、JavaScript モジュールから値をエクスポートするために使用されます。エクスポートされた値は `import` 宣言やダイナミックインポートによって、他のプログラムにインポートすることができます。インポートされたバインディングの値は、それをエクスポートするモジュールの変更の対象となります。モジュールがエクスポートするバインディングの値を更新すると、その更新はインポートされた値として見えます。

ソースファイルで `export` 宣言を使用するためには、そのファイルはランタイムによってモジュールとして解釈される必要があります。HTML では、`<script>` タグに `type="module"` を追加するか、他のモジュールにインポートされることで実現されます。モジュールは自動的に厳格モードで解釈されます。

構文
--

```js
// 個々の機能をエクスポート
export let name1, name2/\*, … \*/; // var も
export const name1 = 1, name2 = 2/\*, … \*/; // var, let も
export function functionName() { /\* … \*/ }
export class ClassName { /\* … \*/ }
export function\* generatorFunctionName() { /\* … \*/ }
export const { name1, name2: bar } = o;
export const [ name1, name2 ] = array;

// リストをエクスポート
export { name1, /\* …, \*/ nameN };
export { variable1 as name1, variable2 as name2, /\* …, \*/ nameN };
export { variable1 as "string name" };
export { name1 as default /\*, … \*/ };

// デフォルトエクスポート
export default expression;
export default function functionName() { /\* … \*/ }
export default class ClassName { /\* … \*/ }
export default function\* generatorFunctionName() { /\* … \*/ }
export default function () { /\* … \*/ }
export default class { /\* … \*/ }
export default function\* () { /\* … \*/ }

// モジュールの集約
export \* from "module-name";
export \* as name1 from "module-name";
export { name1, /\* …, \*/ nameN } from "module-name";
export { import1 as name1, import2 as name2, /\* …, \*/ nameN } from "module-name";
export { default, /\* …, \*/ } from "module-name";
```

`nameN`

エクスポートする識別子（他のスクリプトで `import` を介してインポートできるようにするため）。`as` でエイリアスを使用する場合、実際にエクスポートされる名前を文字列リテラルで指定することができますが、これは有効な識別子とは限りません。

解説
--

各モジュールでは、2 つの異なる種類のエクスポート、**名前付きエクスポート**と**デフォルトエクスポート**を行うことができます。名前付きエクスポートはモジュールごとに複数持てますが、デフォルトエクスポートは 1 つのみです。それぞれのエクスポート方法は、上記の構文のひとつに対応します。

名前付きエクスポート:

```js
// 事前に宣言された機能のエクスポート
export { myFunction2, myVariable2 };

// 個別の機能のエクスポート
// (var, let, const, function, class がエクスポート可能)
export let myVariable = Math.sqrt(2);
export function myFunction() {
  // …
}
```

`export` キーワードの後には、 `let`, `const`, `var` 宣言や、関数、クラス宣言を使用することができます。また、 `export { name1, name2 }` 構文を使用すると、他の場所で宣言された名前のリストをエクスポートすることができます。`export {}` は空のオブジェクトをエクスポートするわけではないことに注意してください。これは何もエクスポートしない（空の名前のリストをエクスポートする）ノーオペレーション宣言です。

エクスポート宣言は一時的なデッドゾーンのルールには従いません。`X` という名前自体が宣言される前に、そのモジュールが `X` をエクスポートすることを宣言することができます。

```js
export { x };
const x = 1;
// これは、`export`が単なる宣言であり、`x`の値を利用しないので、
// 動作します。
```

デフォルトエクスポート:

```js
// デフォルトとして事前に定義された機能のエクスポート
export { myFunction as default };
// これは次のものと同等です
export default myFunction;

// 個別の機能をデフォルトとしてエクスポート
export default function () { /\* … \*/ }
export default class { /\* … \*/ }
```

**メモ:** エクスポート宣言の名前は、互いに異なるものでなければなりません。重複した名前でエクスポートを実施したり、`default` のエクスポートを複数使用すると `SyntaxError` が発生し、モジュールが評価されなくなります。

`export default` 構文ではあらゆる式が許可されます。

```js
export default 1 + 1;
```

特殊なケースとして、関数やクラスは式ではなく *宣言* としてエクスポートされ、これらの宣言は無名にすることができます。つまり、関数は巻き上げが行われることになります。

```js
// これは `foo` は関数宣言であって、関数式ではないため動作します。
foo();

export default function foo() {
  console.log("Hi");
}

// 厳密には宣言であることに変わりはないが、無名であることが許されます。
export default function () {
  console.log("Hi");
}
```

名前付きエクスポートは、複数の値をエクスポートする必要がある場合に有益です。このモジュールをインポートするときは、名前付きエクスポートでは全く同じ名前で参照しなければなりませんが（任意で `as` で名前を変更できます）、デフォルトエクスポートは何か名前を付けてインポートすることができます。例を示します。

```js
// ファイル test.js
const k = 12;
export default k;
```

```js
// 他のファイル
import m from "./test"; // k がデフォルトエクスポートなので、インポートする k の代わりに m を使用することができる点に注意してください
console.log(m); // 12
```

名前の競合を防ぐために、名前付きエクスポートの名前を変更することもできます。

```js
export { myFunction as function1, myVariable as variable };
```

文字列リテラルを使用すると、名前を有効な識別子以外のものに変更することができます。例えば次のようします。

```js
export { myFunction as "my-function" };
```

### 再エクスポート / 集約

親モジュール内の異なるモジュールから「インポート/エクスポート」して、そのモジュールからインポートできるようにすることも可能です。言い換えれば、様々なモジュールからの様々なエクスポートを集約した 1 つのモジュールを作成することができます。

これは "export from" 構文で実現できます。

```js
export { default as function1, function2 } from "bar.js";
```

これは、 `function1` と `function2` がカレントモジュール内で利用できないことを除けば、import と export の組み合わせと同じです。

```js
import { default as function1, function2 } from "bar.js";
export { function1, function2 };
```

ほとんどの "import from" 構文には対応する "export from" 構文があります。

```js
export { x } from "mod";
export { x as v } from "mod";
export \* as ns from "mod";
```

また、`import * from "mod"` はありませんが、`export * from "mod"` はあります。これで `mod` からのすべての **名前付き** エクスポートが現在のモジュールの名前付きエクスポートとして再エクスポートされますが、 `mod` のデフォルトエクスポートは再エクスポートされません。もし、暗黙のうちに同じ名前を再エクスポートする 2 つのワイルドカードの export 文があった場合、どちらも再エクスポートされません。

```js
// -- mod1.js --
export const a = 1;

// -- mod2.js --
export const a = 3;

// -- barrel.js --
export \* from "./mod1.js";
export \* from "./mod2.js";

// -- main.js --
import \* as ns from "./barrel.js";
console.log(ns.a); // undefined
```

重複した名前を直接インポートしようとすると、エラーが発生します。

```js
import { a } from "./barrel.js";
// SyntaxError: The requested module './barrel.js' contains conflicting star exports for name 'a'
```

以下は、import に対応するものですが、構文的には無効です。

```js
export DefaultExport from "bar.js"; // Invalid
```

正しい方法は、エクスポートの名前を変更することです。

```js
export { default as DefaultExport } from "bar.js";
```

export from" 構文では、`as` トークンを省略することができます。これにより、デフォルトエクスポートはデフォルトエクスポートとして再エクスポートされたままとなります。

```js
export { default, function2 } from "bar.js";
```

例
-

### 名前付きエクスポートの使用

`my-module.js` モジュールの中で、以下のコードを含めることができます。

```js
// "my-module.js" モジュール
function cube(x) {
  return x \* x \* x;
}

const foo = Math.PI + Math.SQRT2;

const graph = {
  options: {
    color: "white",
    thickness: "2px",
  },
  draw() {
    console.log("From graph draw function");
  },
};

export { cube, foo, graph };
```

HTML ページの中に含まれる最上位モジュールの中では、次のようにすることができます。

```js
import { cube, foo, graph } from "./my-module.js";

graph.options = {
  color: "blue",
  thickness: "3px",
};

graph.draw();
console.log(cube(3)); // 27
console.log(foo); // 4.555806215962888
```

以下の点に注意することが重要です。

* このスクリプトを HTML の `<script>` 要素で type="module" を指定したものに入れる必要があり、そうすれば適切にモジュールとして認識され、扱われます。
* `file://` の URL で JavaScript モジュールを実行することはできません。— CORS エラーになります。HTTP サーバーを通して実行する必要があります。
### デフォルトエクスポートの使用

値をひとつエクスポートしたい、あるいはモジュールでフォールバック先の値を持ちたい場合は、デフォルトエクスポートを使用するとよいでしょう。

```js
// module "my-module.js"

export default function cube(x) {
  return x \* x \* x;
}
```

別のスクリプトからの、デフォルトエクスポートのインポートは直観的です。

```js
import cube from "./my-module.js";
console.log(cube(3)); // 27
```

### export from の使用

以下のような階層がある場合を例に考えてみましょう。

* `childModule1.js`: `myFunction` および `myVariable` をエクスポート
* `childModule2.js`: `myClass` をエクスポート
* `parentModule.js`: 集約元として機能する（他には何もしない）
* 最上位モジュールである `parentModule.js` のエクスポートを利用する

コードスニペットを使うとこのような感じになります。

```js
// childModule1.js 内
function myFunction() {
  console.log("Hello!");
}
const myVariable = 1;
export { myFunction, myVariable };
```

```js
// childModule2.js 内
class MyClass {
  constructor(x) {
    this.x = x;
  }
}

export { MyClass };
```

```js
// parentModule.js
// childModule1 と childModule2 からのエクスポートを
// 集約して再エクスポートする
export { myFunction, myVariable } from "childModule1.js";
export { MyClass } from "childModule2.js";
```

```js
// 最上位モジュール
// parentModule にモジュールが集約しているので、
// 単一のモジュールからエクスポートを利用できます。
import { myFunction, myVariable, MyClass } from "parentModule.js";
```

仕様書
---

| Specification |
| --- |
| ECMAScript Language Specification # sec-exports |

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

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

関連情報
----

* `import`
* JavaScript モジュール
* ES6 in Depth: Modules Jason Orendorff のブログ記事
* ES modules: A cartoon deep-dive Lin Clark のブログ記事
* Axel Rauschmayer's book: "Exploring JS: Modules"