1

ページに複数のメニューがあり、それらはすべて同じマウスオーバー イベントとクリック イベントを使用するため、関数に組み込むことにしました。ただし、変数は常に hover(function, function) 関数の最後の引数に割り当てられるようです。

$(document).ready( function() {
menuMouseOver = function() {
    for(i=0, u=arguments.length; i<u; i++){
        var parent = arguments[i].parent;
        var active = arguments[i].active;
        var childSelect = arguments[i].childSelect;
        console.log(active); //logs the correct active
            $(parent).children(childSelect)
                .not('.'+active).each( function(i, e) {console.log(active);})
 //The above console.log logs the correct active 
                    .hover( function() {
                            console.log(active); //this one always logs menu2_active
                            $(this).addClass(active);
                        }, function() {
                            $(this).removeClass(active);
                        });
    }
}
menuMouseOver( { parent: '#menu1',
                active: 'menu1_active',
                childSelect: ':gt(0)'},
            { parent: '#menu2',
                active: 'menu2_active',
                childSelect: ':gt(0)'});
});

最後の console.log が常に、arguments[i].active に属するものではなく、最後のアクティブをログに記録するのはなぜですか。(この例では、arguments[1].active のアクティブを常にログに記録します) 何が間違っていますか?

また、実際の関数はより複雑ですが、このバリアントにも問題があります。

4

3 に答える 3

4

JavaScript にはブロック スコープがないため、for ループで宣言した変数の値は反復ごとに変更され、それらの関数はすべて同じ変数を参照します。秘訣は、for ループ内に新しい関数スコープを作成して、宣言した変数がその反復中にバインドされるようにすることです。

これは、ループ内で無名関数を実行することで実現できます。

menuMouseOver = function() {
    for(i=0, u=arguments.length; i<u; i++){
      (function(){ // anonymous function to create new scope
        var parent = arguments[i].parent;
        var active = arguments[i].active;
        var childSelect = arguments[i].childSelect;
        console.log(active); //logs the correct active
            $(parent).children(childSelect)
                .not('.'+active).each( function(i, e) {console.log(active);})
 //The above console.log logs the correct active 
                    .hover( function() {
                            console.log(active); //this one always logs menu2_active
                            $(this).addClass(active);
                        }, function() {
                            $(this).removeClass(active);
                        });
       })(); // execute the anonymous function
    }
}

以前の方法では、すべての関数が同じ変数参照を閉じていたため、関数が作成されたときの値ではなく、最後の値が何であれ使用されていました。関数スコープを使用すると、意図したとおりに動作します。

于 2009-01-29T18:05:42.387 に答える
1

あなたの問題は、ホバーイベントが実行中のメソッドの範囲外で発生することです。したがって、ホバーが実行されるまでに、アクティブな変数はすでにセット全体を通過しており、最後の要素のアクティブな状態に留まっています。この問題が発生しているのは、最後のログがスコープ外のイベントであり、他の 2 つがループ内のスコープ内にあるためです。

これを試して:

        $(parent).children(childSelect)
            .not('.'+active).each( function(i, e) {
                console.log(active);
                $(this).data("active", active);
            })
            .hover( function() {
                $(this).addClass($(this).data("active"));
            }, function() {
                $(this).removeClass($(this).data("active")));
            });

これにより、実際には「アクティブな」値が DOM 要素内に格納され、スコープ内でアクセスできるようになります。

于 2009-01-29T17:40:38.087 に答える
0

奇妙な問題なので頭を悩ませていますが、関数を少しリファクタリングしました。役に立つかもしれません(ああ、その間にもっと賢い人が答えました):

$("#menu1,#menu2").each(function(){
    var id = $(this).attr("id");
    $(">li",this).not("."+id+"_active,:eq(0)").hover(function(){
        $(this).addClass(id+"_active");
    },function(){
        $(this).removeClass(id+"_active");
    });
});
于 2009-01-29T18:04:27.867 に答える