ホームページ > ウェブフロントエンド > jsチュートリアル > Javascript ループがイベント ハンドラーで予期しない動作を引き起こすのはなぜですか?

Javascript ループがイベント ハンドラーで予期しない動作を引き起こすのはなぜですか?

DDD
リリース: 2024-12-22 06:26:38
オリジナル
293 人が閲覧しました

Why Do Javascript Loops Cause Unexpected Behavior in Event Handlers?

JavaScript の悪名高いループ問題が再考

JavaScript の悪名高いループ問題は、開発者を困惑させ続けています。次のコード スニペットを考えてみましょう:

function addLinks () {
    for (var i=0, link; i<5; i++) {
        link = document.createElement("a");
        link.innerHTML = "Link " + i;
        link.onclick = function () {
            alert(i);
        };
        document.body.appendChild(link);
    }
}
ログイン後にコピー

このコードは、現在のリンク ID を表示する onClick イベントを持つ 5 つのリンクを作成することを目的としています。ただし、これらのリンクをクリックすると、すべて「リンク 5」が表示されます。

この問題の根本原因は、JavaScript の関数レベルのスコープにあります。ループが完了すると、変数 i は値 5 を保持します。これは、Javascript 関数がその字句環境に対して閉じられており、周囲のスコープで定義された変数にアクセスできるためです。

この問題の回避策各反復で i の現在値をキャプチャするクロージャを導入することです:

function addLinks () {
    for (var i=0, link; i<5; i++) {
        link = document.createElement("a");
        link.innerHTML = "Link " + i;
        link.onclick = function (num) {
            return function () {
                alert(num);
            };
        }(i);
        document.body.appendChild(link);
    }
}
ログイン後にコピー

このコードでは、リンクごとに新しい関数オブジェクトが作成されます。これには独自のスコープと、i の現在の値が割り当てられるローカル変数 num があります。内部関数が実行されると、クロージャの num 変数が参照され、ループ内に割り当てられた正しい値が保持されます。

このアプローチは効果的ですが、新しい関数が作成されるため、パフォーマンスが低下します。すべてのイベントリスナーに対して。より効率的な代替方法は、データ ストレージに DOM ノード自体を使用することです。

function linkListener() {
    alert(this.i);
}

function addLinks () {
    for(var i = 0; i < 5; ++i) {
        var link = document.createElement('a');
        link.appendChild(document.createTextNode('Link ' + i));
        link.i = i;
        link.onclick = linkListener;
        document.body.appendChild(link);
    }
}
ログイン後にコピー

i 値を DOM ノードに直接保存することで、クロージャの必要性がなくなり、コードの効率が向上します。

以上がJavascript ループがイベント ハンドラーで予期しない動作を引き起こすのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート