ホームページ > 記事 > ウェブフロントエンド > ループ内のクロージャによりすべてのリンクが同じ値を表示するのはなぜですか?
クロージャを理解する
JavaScript のクロージャを使用すると、関数が直接の外部から変数にアクセスできるようになりますスコープ、プライベート データ コンテキストの作成。ただし、クロージャによって参照される変数は、外側の関数の実行が終了した後でもアクセス可能なままです。
ループ内のクロージャの問題
次のコード スニペットを考えてみましょう:
<code class="javascript">for (var i = 0; i < 5; i++) { link = document.createElement("a"); link.innerHTML = "Link " + i; link.onclick = function (num) { return function () { alert(num); }; }(i); document.body.appendChild(link); }</code>
この例では、内部関数に num として渡された i の値が、すべてのリンク要素にわたって「共有変数」を作成するクロージャによってキャプチャされます。これは、リンクをクリックすると常に i の最後の値 (この場合は 4) が表示されることを意味します。
関数ファクトリとして IIFE (即時に呼び出される関数式) を使用する
この問題を解決するには、リンクごとに IIFE を作成し、i の値を引数として渡します。
<code class="javascript">function addLinks() { for (var i = 0; i < 5; i++) { link = document.createElement("a"); link.innerHTML = "Link " + i; // IIFE used as a function factory link.onclick = (function (num) { return function () { alert(num); }; })(i); document.body.appendChild(link); } }</code>
このバージョンでは、各 IIFE は i の値が固定された独立したスコープを作成します。関数の作成時刻。これにより、クリックされた順序に関係なく、各リンク要素が i の独自のプライベート コピーを持つことが保証されます。
代替アプローチ: 関数ジェネレーター
別のオプションは次のとおりです。関数ジェネレーターを使用して i の現在値を参照する関数を作成するには:
<code class="javascript">function generateMyHandler(x) { return function () { alert(x); }; } for (var i = 0; i < 5; i++) { link = document.createElement("a"); link.innerHTML = "Link " + i; link.onclick = generateMyHandler(i); document.body.appendChild(link); }</code>
この場合、generateMyHandler 関数は、次の時点で i の特定の値にバインドされた新しい関数を返します。関数呼び出し。
JavaScript クロージャーが変数をキャプチャする方法を理解し、適切な手法を使用して分離されたスコープを作成することで、開発者は共有変数を含む複雑なループ シナリオを効果的に処理できます。
以上がループ内のクロージャによりすべてのリンクが同じ値を表示するのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。