From b033d42d6d8e4fdaf67b7cd7b1b8a153e12379e1 Mon Sep 17 00:00:00 2001 From: Masahiro FUJIMOTO Date: Sun, 13 Oct 2024 10:43:00 +0900 Subject: [PATCH] =?UTF-8?q?2024/07/26=20=E6=99=82=E7=82=B9=E3=81=AE?= =?UTF-8?q?=E8=8B=B1=E8=AA=9E=E7=89=88=E3=81=AB=E5=9F=BA=E3=81=A5=E3=81=8D?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../statements/async_function/index.md | 159 ++++++++++-------- .../reference/statements/for...of/index.md | 31 ++-- 2 files changed, 104 insertions(+), 86 deletions(-) diff --git a/files/ja/web/javascript/reference/statements/async_function/index.md b/files/ja/web/javascript/reference/statements/async_function/index.md index c8fa2b5bb67e9c..e44b824f35fa44 100644 --- a/files/ja/web/javascript/reference/statements/async_function/index.md +++ b/files/ja/web/javascript/reference/statements/async_function/index.md @@ -2,14 +2,14 @@ title: async function slug: Web/JavaScript/Reference/Statements/async_function l10n: - sourceCommit: d85a7ba8cca98c2f6cf67a0c44f0ffd467532f20 + sourceCommit: 3f91fdcc678991410f4f5adcbff44d1b3b1ede88 --- {{jsSidebar("Statements")}} -**`async function`** 宣言は非同期関数を宣言し、その中で `await` キーワードを使うことができます。`async` および `await` キーワードを使用することで、プロミスベースの非同期の動作を、プロミスチェーンを明示的に構成する必要なく、よりすっきりとした方法で書くことができます。 +**`async function`** 宣言は、与えられた名前で新しい非同期関数の{{Glossary("binding","バインド")}}を作成します。その関数の本体の中では `await` キーワードを使うことができ、ます。`async` および `await` キーワードを使用することで、プロミスベースの非同期の動作を、プロミスチェーンを明示的に構成する必要なく、よりすっきりとした方法で書くことができます。 -非同期関数は{{jsxref("Operators/async_function", "式として", "", 1)}}も定義することができます。 +非同期関数は [`async function` 式](/ja/docs/Web/JavaScript/Reference/Operators/async_function)を使用して定義することもできます。 {{EmbedInteractiveExample("pages/js/statement-async.html", "taller")}} @@ -22,26 +22,27 @@ async function name(param0) { async function name(param0, param1) { statements } -async function name(param0, param1, /* … ,*/ paramN) { +async function name(param0, param1, /* …, */ paramN) { statements } ``` +> [!NOTE] +> 改行を `async` と `function` の間に入れてはいけません。そうしないとセミコロンが[自動的に挿入され](/ja/docs/Web/JavaScript/Reference/Lexical_grammar#自動セミコロン挿入)、`async` が識別子となり、残りが `function` 宣言となります。 + ### 引数 - `name` - : 関数の名前です。 - `param` {{optional_inline}} - - : 関数に渡す引数の名前です。 + - : 関数の正式な引数の名前です。引数の構文については、[関数リファレンス](/ja/docs/Web/JavaScript/Guide/Functions#関数の引数)を参照してください。 - `statements` {{optional_inline}} - : 関数の本体を構成する文です。`await` の仕組みを使用することができます。 -### 返値 - -{{jsxref("Promise")}} で、非同期関数から返される値で解決するか、または非同期関数内で捕捉されなかった例外で拒否されます。 - ## 解説 +`async function` 宣言は、{{jsxref("AsyncFunction")}} オブジェクトを作成します。非同期関数が呼び出されるたびに、新しいプロミス ({{jsxref("Promise")}}) が返され、非同期関数によって返された値で解決されます。または、非同期関数内で捕捉されなかった例外で拒否されます。 + 非同期関数には、 {{jsxref("Operators/await", "await")}} 式を置くことができます。 await 式は返されたプロミスが履行されるか拒否されるまで実行を中断することで、プロミスを返す関数をあたかも同期しているかのように動作させます。プロミスの解決済みの値は、await 式の返値として扱われます。`async` と `await` を使用すると、非同期コードに通常の `try` / `catch` ブロックを使用することができます。 > [!NOTE] @@ -69,32 +70,26 @@ function foo() { } ``` -> [!NOTE] -> -> 非同期関数の返値が `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 -> ``` +たとえ非同期関数の返値が `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 式がある場合、非同期関数は常に非同期に完了します。 +非同期関数の本体は、0 個以上の await 式で分割されていると考えることができます。最上位のコードは、最初の await 式(ある場合)まで含めて同期的に実行されます。この方法では、await 式のない非同期関数は同期的に実行されます。しかし、関数本体内に await 式がある場合、非同期関数は常に非同期的に完了します。 例: @@ -145,7 +140,7 @@ async function foo() { foo().catch(() => {}); // すべてのエラーを浅くしようとする... ``` -`async function` 宣言はスコープの上端まで[巻き上げられ](/ja/docs/Glossary/Hoisting)、スコープのどこからでも呼び出すことができます。 +`async function` 宣言は、{{jsxref("Statements/function", "function")}} 宣言と似た挙動をします。つまり、[巻き上げ](/ja/docs/Glossary/Hoisting)によりスコープの先頭に移動し、スコープ内のどこからでも呼び出すことができます。また、特定のコンテキストでのみ再宣言することができます。 ## 例 @@ -173,74 +168,87 @@ function resolveAfter1Second() { } async function sequentialStart() { - console.log("==SEQUENTIAL START=="); + console.log("== sequentialStart 開始 =="); - // 1. これは即時実行される - const slow = await resolveAfter2Seconds(); - console.log(slow); // 2. これは 1. の 2 秒後に実行される + // 1. タイマーの起動、完了後にログ出力 + const slow = resolveAfter2Seconds(); + console.log(await slow); - const fast = await resolveAfter1Second(); - console.log(fast); // 3. これは 1. の 3 秒後に実行される + // 2. 前回のタイマーを待った後で次のタイマーを開始 + const fast = resolveAfter1Second(); + console.log(await fast); + + console.log("== sequentialStart 終了 =="); } -async function concurrentStart() { - console.log("==CONCURRENT START with await=="); - const slow = resolveAfter2Seconds(); // ただちにタイマーを起動 - const fast = resolveAfter1Second(); // ただちにタイマーを起動 +async function sequentialWait() { + console.log("== sequentialWait 開始 =="); + + // 1. 2 つのタイマーを同時に開始するには、お互いを待つ必要はない + const slow = resolveAfter2Seconds(); + const fast = resolveAfter1Second(); - // 1. これは即時実行される - console.log(await slow); // 2. これは 1. の 2 秒後に実行される - console.log(await fast); // 3. fast はすでに解決しているので、これは 1. の 2 秒後 (2.の直後) に実行される + // 2. slow タイマーが完全に終了するまで待ち、その後、結果をログ出力する + console.log(await slow); + // 3. fast タイマーが完全に終了するまで待ち、その後、結果をログ出力する + console.log(await fast); + + console.log("== sequentialWait 終了 =="); } -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 concurrent1() { + console.log("== concurrent1 開始 =="); + + // 1. 2 つのタイマーを同時に開始し、どちらも完了するのを待つ + const results = await Promise.all([ + resolveAfter2Seconds(), + resolveAfter1Second(), + ]); + // 2. それぞれログ出力する + console.log(results[0]); + console.log(results[1]); + + console.log("== concurrent1 終了 =="); } -async function parallel() { - console.log("==PARALLEL with await Promise.all=="); +async function concurrent2() { + console.log("== concurrent2 開始 =="); // 2 つの jobs を並列に実行し両方が完了するのを待つ await Promise.all([ (async () => console.log(await resolveAfter2Seconds()))(), (async () => console.log(await resolveAfter1Second()))(), ]); + console.log("== concurrent2 終了 =="); } sequentialStart(); // 2 秒後に "slow" をログ出力し、その 1 秒後に "fast" をログ出力する // 直前の処理を待つ -setTimeout(concurrentStart, 4000); // 2 秒後に "slow" と "fast" をログ出力する +setTimeout(sequentialWait, 4000); // 2 秒後に "slow" と "fast" をログ出力する // 直前の処理を待つ -setTimeout(concurrentPromise, 7000); // concurrentStart と同様 +setTimeout(concurrent1, 7000); // concurrentStart と同様 // 直前の処理を待つ -setTimeout(parallel, 10000); // 本当に並列処理となるため 1 秒後に "fast" とログ出力し、その 1 秒後に "slow" とログ出力する +setTimeout(concurrent2, 10000); // 本当に並列処理となるため 1 秒後に "fast" とログ出力し、その 1 秒後に "slow" とログ出力する ``` -#### await と並列性 +#### await と並行性 `sequentialStart` では、最初の `await` のために実行が 2 秒間待機し、 2 つ目の `await` のためにさらに 1 秒間待機します。 2 つ目のタイマーは最初のタイマーが起動している間は作成されません。コードは 3 秒後に終了します。 -`concurrentStart` では、両方のタイマーが作成され、両方とも `await` される、すなわち待機させられます。タイマーは同時に実行されているため、 3 秒後ではなく 2 秒後に、すなわち最も遅いタイマーにあわせて終了します。 +`sequentialWait` では、両方のタイマーが作成され、両方とも `await` される、すなわち待機させられます。タイマーは同時に実行されているため、 3 秒後ではなく 2 秒後に、すなわち最も遅いタイマーにあわせて終了します。 しかし、 `await` の呼び出しは依然として逐次処理であり、これは 2 つ目の `await` が 1 つ目の終了まで待つことを意味します。このケースでは、最も速いタイマーが最も遅いタイマーのあとに処理されることになります。 -複数の処理を安全に並列に実行したい場合は、 [`Promise.all`](/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise/all) または -[`Promise.allSettled`](/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise/allSettled) の呼び出しで待つ必要があります。 +複数の処理を安全に並行に実行したい場合は、{{jsxref("Promise.all()")}} または {{jsxref("Promise.allSettled()")}} の呼び出しで待つ必要があります。 > [!WARNING] -> 関数 `concurrentStart` と `concurrentPromise` は機能的に同等ではありません。 +> 関数 `sequentialWait` と `concurrent1` は機能的に同等ではありません。 > -> `concurrentStart` では、プロミス `fast` がプロミス `slow` の履行よりも前に拒否された場合、呼び出し元が catch 節を構成しているかどうかにかかわらず、プロミスの拒否が処理されないというエラーが発生します。 +> `sequentialWait` では、プロミス `fast` がプロミス `slow` の履行よりも前に拒否された場合、呼び出し元が catch 節を構成しているかどうかにかかわらず、プロミスの拒否が処理されないというエラーが発生します。 > -> `concurrentPromise` では、`Promise.all` がプロミスチェーンを一括して配線します。つまり、操作はプロミスの拒否の順番に関係なくすばやく失敗し、エラーは構成されたプロミスチェーン内で常に発生するため、通常の方法で捕捉することができます。 +> `concurrent1` では、`Promise.all` がプロミスチェーンを一括して配線します。つまり、操作はプロミスの拒否の順番に関係なくすばやく失敗し、エラーは構成されたプロミスチェーン内で常に発生するため、通常の方法で捕捉することができます。 ### プロミスチェーンを非同期関数で書き換える @@ -277,7 +285,7 @@ async function getProcessedData(url) { } ``` -二番目の例では、有効であるにもかかわらず、 `await` 文が `return` キーワードの後にないことに注意してください。非同期関数の返値は、(この例のように)既にプロミスでない限り、暗黙的に {{jsxref("Promise.resolve")}} でラップされるからです。 +2 番目の例では、有効であるにもかかわらず、`await` 文が `return` キーワードの後にないことに注意してください。非同期関数の返値は、(この例のように)既にプロミスになっていない場合、暗黙的に {{jsxref("Promise.resolve")}} でラップされるからです。 ## 仕様書 @@ -289,7 +297,14 @@ async function getProcessedData(url) { ## 関連情報 -- {{jsxref("Operators/async_function", "非同期関数式", "", 1)}} -- {{jsxref("AsyncFunction")}} オブジェクト +- [関数](/ja/docs/Web/JavaScript/Guide/Functions)ガイド +- [プロミスの使用](/ja/docs/Web/JavaScript/Guide/Using_promises)ガイド +- [関数](/ja/docs/Web/JavaScript/Reference/Functions) +- {{jsxref("AsyncFunction")}} +- [`async function` 式](/ja/docs/Web/JavaScript/Reference/Operators/async_function) +- {{jsxref("Statements/function", "function")}} +- {{jsxref("Statements/function*", "function*")}} +- {{jsxref("Statements/async_function*", "async function*")}} - {{jsxref("Operators/await", "await")}} -- [Decorating Async JavaScript Functions](https://innolitics.com/10x/javascript-decorators-for-promise-returning-functions/) (_innolitics.com_) +- {{jsxref("Promise")}} +- [Decorating async JavaScript functions](https://innolitics.com/10x/javascript-decorators-for-promise-returning-functions/) (innolitics.com, 2016) diff --git a/files/ja/web/javascript/reference/statements/for...of/index.md b/files/ja/web/javascript/reference/statements/for...of/index.md index ac495519f262e9..962a4c257aae4b 100644 --- a/files/ja/web/javascript/reference/statements/for...of/index.md +++ b/files/ja/web/javascript/reference/statements/for...of/index.md @@ -2,7 +2,7 @@ title: for...of slug: Web/JavaScript/Reference/Statements/for...of l10n: - sourceCommit: 0f3738f6b1ed1aa69395ff181207186e1ad9f4d8 + sourceCommit: 3f91fdcc678991410f4f5adcbff44d1b3b1ede88 --- {{jsSidebar("Statements")}} @@ -20,7 +20,7 @@ for (variable of iterable) ``` - `variable` - - : 反復処理の各回において、一連のデータから値を受け取ります。[`const`](/ja/docs/Web/JavaScript/Reference/Statements/const), [`let`](/ja/docs/Web/JavaScript/Reference/Statements/let), [`var`](/ja/docs/Web/JavaScript/Reference/Statements/var) の何れかで定義されたものか、[代入](/ja/docs/Web/JavaScript/Reference/Operators/Assignment)のターゲットとなります(以前に宣言した変数や、オブジェクトプロパティなど)。 + - : 反復処理の各回において、一連のデータから値を受け取ります。[`const`](/ja/docs/Web/JavaScript/Reference/Statements/const), [`let`](/ja/docs/Web/JavaScript/Reference/Statements/let), [`var`](/ja/docs/Web/JavaScript/Reference/Statements/var) の何れかで定義されたものか、[代入](/ja/docs/Web/JavaScript/Reference/Operators/Assignment)のターゲットとなります(以前に宣言した変数や、オブジェクトプロパティ、[分割代入パターン](/ja/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)など)。`var` で宣言された変数はループのローカル変数ではなく、すなわち `for...of` ループと同じスコープになります。 - `iterable` - : 反復可能オブジェクトです。ループを実行する一連の値の元となるものです。 - `statement` @@ -30,9 +30,12 @@ for (variable of iterable) `for...of` ループは、反復可能オブジェクトから取り出した値を 1 つずつ順次処理します。ループが値に対して行う各処理は反復処理と呼ばれ、ループは反復可能オブジェクトを反復処理すると言います。それぞれの反復処理では、現在のシーケンス値を参照する可能性のある文が実行されます。 -`for...of` ループが反復可能オブジェクトを反復処理する場合、最初にその反復可能オブジェクトの [`[@@iterator]()`](/ja/docs/Web/JavaScript/Reference/Global_Objects/Symbol/iterator) メソッドが呼び出されます。これは[イテレーター](/ja/docs/Web/JavaScript/Reference/Iteration_protocols#イテレータープロトコル)を返すので、その返されたイテレーターの [`next()`](/ja/docs/Web/JavaScript/Reference/Iteration_protocols#イテレータープロトコル) メソッドを呼び出すことで、`variable` に代入される一連の値を生成することができます。 +`for...of` ループが反復可能オブジェクトを反復処理する場合、最初にその反復可能オブジェクトの [`[Symbol.iterator]()`](/ja/docs/Web/JavaScript/Reference/Global_Objects/Symbol/iterator) メソッドが呼び出されます。これは[イテレーター](/ja/docs/Web/JavaScript/Reference/Iteration_protocols#イテレータープロトコル)を返すので、その返されたイテレーターの [`next()`](/ja/docs/Web/JavaScript/Reference/Iteration_protocols#イテレータープロトコル) メソッドを呼び出すことで、`variable` に代入される一連の値を生成することができます。 -`for...of` ループは、イテレーターが完全に処理したときに終了します(イテレーターの `next()` メソッドは `done: true` を含むオブジェクトを返します)。また、通常の制御フローを変更するために制御フロー文を使用することもできます。[`break`](/ja/docs/Web/JavaScript/Reference/Statements/break) はループを抜けてループ本体の後の最初のステートメントに進み、[`continue`](/ja/docs/Web/JavaScript/Reference/Statements/continue) は現在の反復処理の残りの文をスキップして次の反復処理に進みます。 +`for...of` ループは、イテレーターが完全に処理された時点で終了します(`next()` の結果は、`done: true` を持つオブジェクトです)。他のループ文と同様に、[フロー制御文](/ja/docs/Web/JavaScript/Reference/Statements#フロー制御)を `statement` 内部で使用することができます。 + +- {{jsxref("Statements/break", "break")}} は、`statement` の実行を停止し、ループの後の最初の文に移動します。 +- {{jsxref("Statements/continue", "continue")}} は `statement` の実行を停止し、ループの次の反復処理に移ります。 `for...of` ループが早期に終了した場合(例えば、`break` 文に遭遇したり、エラーが発生した場合)、[`return()`](/ja/docs/Web/JavaScript/Reference/Iteration_protocols#イテレータープロトコル) のメソッドが呼び出されクリーンアップ処理が行われます。 @@ -53,11 +56,11 @@ for (let value of iterable) { > [!NOTE] > 反復処理ごとに新しい変数が作成されます。ループ本体内で変数を再代入しても、反復可能オブジェクト(この場合は配列)の元の値には影響しません。 -[分割代入](/ja/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)や、`for (x.y of iterable)` などのオブジェクトプロパティを使用することもできます。 +[分割代入](/ja/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)を使用して複数のローカル変数に代入することもできますし、 `for (x.y of iterable)` のようなプロパティアクセサーを使用して、オブジェクトプロパティに値を代入することもできます。 しかし、特別なルールにより、変数名として `async` を使用することは禁じられています。これは無効な構文です。 -```js example-bad +```js-nolint example-bad let async; for (async of [1, 2, 3]); // SyntaxError: The left-hand side of a for-of loop may not be 'async'. ``` @@ -81,7 +84,7 @@ for (const value of iterable) { ### 文字列に対する反復処理 -文字列は [Unicode コードポイントで反復処理します](/ja/docs/Web/JavaScript/Reference/Global_Objects/String/@@iterator)。 +文字列は [Unicode コードポイント単位で反復処理します](/ja/docs/Web/JavaScript/Reference/Global_Objects/String/Symbol.iterator)。 ```js const iterable = "boo"; @@ -173,7 +176,7 @@ for (const paragraph of articleParagraphs) { ### ユーザー定義の反復可能オブジェクトに対する反復処理 -独自のイテレーターを返す `@@iterator` メソッドで、オブジェクトを反復処理します。 +独自のイテレーターを返す `[Symbol.iterator]()` メソッドで、オブジェクトを反復処理します。 ```js const iterable = { @@ -198,7 +201,7 @@ for (const value of iterable) { // 3 ``` -オブジェクトを `@@iterator` ジェネレーターメソッドで反復処理します。 +オブジェクトを `[Symbol.iterator]()` ジェネレーターメソッドで反復処理します。 ```js const iterable = { @@ -217,7 +220,7 @@ for (const value of iterable) { // 3 ``` -反復可能なイテレーター(`this` を返す `[@@iterator]()` メソッドを持つイテレーター)は、`for...of` などのイテレーターを想定した構文でイテレーターを使用可能にする、かなり一般的なテクニックです。 +反復可能なイテレーター(`this` を返す `[Symbol.iterator]()` メソッドを持つイテレーター)は、`for...of` などのイテレーターを想定した構文でイテレーターを使用可能にする、かなり一般的なテクニックです。 ```js let i = 1; @@ -263,7 +266,7 @@ for (const value of generator) { ### 早期の脱出 -最初のループで `break` ステートメントを実行すると、ループが早期に終了します。イテレーターはまだ完了していないので、2 つ目のループは最初のループが停止したところから継続されます。 +最初のループで `break` 文を実行すると、ループが早期に終了します。イテレーターはまだ完了していないので、2 つ目のループは最初のループが停止したところから継続されます。 ```js const source = [1, 2, 3]; @@ -295,7 +298,7 @@ for (const value of iterator) { // [出力なし] ``` -ジェネレーターは [`return()`](/ja/docs/Web/JavaScript/Reference/Global_Objects/Generator/return) メソッドを実装しており、ループが終了するとジェネレーター関数が早期復帰するように発生しています。このため、ジェネレータはループ間で再利用することができません。 +ジェネレーターは [`return()`](/ja/docs/Web/JavaScript/Reference/Global_Objects/Generator/return) メソッドを実装しており、ループが終了するとジェネレーター関数が早期復帰するように発生しています。このため、ジェネレーターはループをまたいで再利用することができません。 ```js example-bad function* source() { @@ -362,7 +365,7 @@ for (const i of iterable) { 2 番目のループは最初のものと似ていますが、{{jsxref("Object.hasOwn()")}} を使用して見つかった列挙可能なプロパティがオブジェクト自身のものであるか、すなわち継承したものでないかどうかをチェックしています。オブジェクト自身のプロパティである場合は、ログ出力します。`0`, `1`, `2`, `foo` は自身のプロパティであるため出力されます。`arrCustom` と `objCustom` は継承されたものであるために出力されません。 -このループは、`iterable` が[反復可能オブジェクト](/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/@@iterator)として定義している順序で _値_ を反復処理し、ログ出力します。オブジェクトの _要素_ である `3`, `5`, `7` は表示されますが、オブジェクトの _プロパティ_ は表示されません。 +`for...of` ループは、`iterable` が[反復可能オブジェクト](/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/Symbol.iterator)として定義している順序で _値_ を反復処理し、ログ出力します。オブジェクトの _要素_ である `3`, `5`, `7` は表示されますが、オブジェクトの _プロパティ_ は表示されません。 ## 仕様書 @@ -376,4 +379,4 @@ for (const i of iterable) { - {{jsxref("Array.prototype.forEach()")}} - {{jsxref("Map.prototype.forEach()")}} -- {{jsxref("Object.entries()")}} – オブジェクトに `for...of` を使用するときに便利です。 +- {{jsxref("Object.entries()")}}