1

私は可変スコープの問題を抱えていますが、なぜこれが発生するのか、そしてそれを取り除く方法がわかりません:

    var items = ['foo', 'bar'];
    for (var index in items) {
        var item = items[index];
        var selector = '.'+item+'-class';
        $(selector).bind('click', function() {
            console.log("class: "+$(this).attr('class'));
            console.log("selector: "+selector);
            console.log("item: "+item);
        });
    }

このコードは、次のHTML上で実行されると見なされます。

<div class="foo-class">Foo</div>
<div class="bar-class">Bar</div>

「Foo」をクリックすると、最初の行に正しいクラス(つまり、「foo-class」)がエコーされますが、セレクターとそれに続くアイテム名はバーに関連しています。問題は、ループの2回目の反復で、最初の反復で使用された変数がリセットされることだと思います。

ループ内の宣言は、このレベルでスコープを明確に宣言する必要があると思いました。私が間違っている ?なんで ?どうすれば修正できますか?

私は回避策を求めていません。何かクリーンで、javascript変数スコープのメカニズムをよりよく理解したいと思っています。

ここにjsfiddleがあります。

ありがとう !

4

5 に答える 5

4

これが更新されたフィドルの例です。

var items = ['foo', 'bar'];
for (var index in items) {
    (function() {
        var item = items[index]; 
        var selector = '.' + item + '-class';
        $(selector).bind('click', function() {
            console.log("class: " + $(this).attr('class'));
            console.log("selector: " + selector);
            console.log("item: " + item);
        });
    })();
}​

匿名関数を作成すると、定義した変数ごとに新しいスコープが定義されます

ヒント:コードをよりクリーンに保つために、バインドを実行するための別の関数を作成してみてください。

于 2012-04-12T20:58:42.963 に答える
1

問題は厳密には可変スコープに関するものではありません。匿名関数は、ループで定義しているときではなく、クリックイベントがトリガーされたときに実行されます。あなたの例と機能的に同一である以下を考慮してください:

var items = ['foo', 'bar'];

for (var index in items) {
    var item = items[index];
    var selector = '.'+item+'-class';
    $(selector).bind( 'click', test );
}
​
function test() {
    console.log("selector: "+selector);
}

これは(うまくいけば)何が起こっているかを示しています。関数のグローバル変数selectorは、関数が呼び出されているとき、どちらの場合も同じです(「バー」)。

于 2012-04-12T21:03:41.197 に答える
1

これらのforループ(google it)でも常に同じです。JavaScriptにはブロックスコープではなく関数スコープがあるため、アイテムをクリックすると、1つの変数selectorが最後のループ実行後の値になります(変数についても同じですitem)。

この問題を解決するには、変数を独自のスコープに格納するループ内の別のクロージャが必要です。つまり、ループを実行するたびに関数を実行する必要があります。

于 2012-04-12T20:56:58.493 に答える
0
var items = ['foo', 'bar'];
for (var index in items) {
    (function(i){  
    var item = items[i];
    var selector = '.'+item+'-class';
    $(selector).bind('click', function() {
            console.log("class: "+$(this).attr('class'));
            console.log("selector: "+selector);
            console.log("item: "+item);
        });
    })(index);
}

ここをいじる。

于 2012-04-12T21:07:57.627 に答える
0

変数「selector」と「item」は、値を格納する場所への参照であり、htl要素の1つをクリックした時点でのこれら2つの値は、最後のループからのものです。

于 2012-04-12T21:09:34.447 に答える