1

重複の可能性:
JavaScript クロージャーと変数スコープ
for ループでクリック ハンドラーを割り当てる

私はこのスクリプトを持っています:

var MyClass = {
    MyArray: new Array(0, 1, 2, 3, 4),

    MyFunc1: function() {
        var i = 0;
        for (i = MyClass.MyArray.length - 1; i>=0; i--) {
            var cen = document.getElementById("cen_" + i); // It is an img element
                cen.src = "col.png";
                cen.className = "cen_act";
                cen.onclick = function() { MyClass.MyFunc1(i); };
            } else {
                cen.src = "no.png";
                cen.className = "cen";
                cen.onclick = null;
            }
        }
    },

    MyFunc2: function(id) {
        alert(id);
    }
}

私の問題は、この行で、cen.onclick = function() { MyClass.MyFunc1(i); };送信される引数MyFunc2が常に-1であることです。この関数は、それぞれにonclickイベントMyFunc1を持つ 4 つの画像を作成する必要があります。各画像をクリックすると、MyFunc2 関数は対応する i値を表示するはずです。i値は、作成された各イベントとイメージ要素に対して「保存」されていないように見えますが、その「ポインター」のみが保存されています。

ありがとう!

4

3 に答える 3

2

これが起こる理由を理解するには、 JavaScript クロージャーの概念に精通している必要があります。もしそうなら、あなたは覚えておくべきです

function() { MyClass.MyFunc1(i); };

関数クロージャーにはiの値が含まれます-1(ループ全体の実行が終了した後のこの変数の最終bind値であるため)。これを回避するには、次のいずれかを使用できます。

cen.onclick = (function(i) { MyClass.MyFunc1(i); }).bind(null, i);

または、適切な値で明示的に作成されたクロージャーを使用しiます。

于 2012-05-17T14:37:09.137 に答える
1

これは通常のケースであり、クロージャーの誤解です。このスレッドを参照してください。手がかりが得られる場合があります。この問題を修正する簡単な方法は、forループ本体を即時呼び出し関数式でラップすることです。

MyFunc1: function() {
    var i = 0;
    for (i = MyClass.MyArray.length - 1; i>=0; i--) {
        (function(i) {
            var cen = document.getElementById("cen_" + i); // An img element
                cen.src = "col.png";
                cen.className = "cen_act";
                cen.onclick = function() { MyClass.MyFunc2(i); };
            } else {
                cen.src = "no.png";
                cen.className = "cen";
                cen.onclick = null;
            }
        }(i));
    }
}
于 2012-05-17T14:36:49.357 に答える
1

ループ内で変化する変数をキャプチャしているため、常に i の最後の値を取得します。

クロージャーを作成することで簡単に修正できます。

MyFunc1: function() {
    var i = 0;
    for (i = MyClass.MyArray.length - 1; i>=0; i--) {
        (function(i) {

        var cen = document.getElementById("cen_" + i); // An img element
            cen.src = "col.png";
            cen.className = "cen_act";
            cen.onclick = function() { MyClass.MyFunc2(i); };
        } else {
            cen.src = "no.png";
            cen.className = "cen";
            cen.onclick = null;
        }
       })(i);
    }
},
于 2012-05-17T14:37:48.247 に答える