2012-02-08 5 views
1

JavaSriptのプロパティをfor loopに割り当てる方法が間違っているのですが、どうすればこの問題を解決できますか? first testなぜこのループの後に最後のIDの小道具しか得られないのですか?

var setImageSize = function (i) { 

    instances[i].img = $('<img id="jquery-background-zoom-'+i+'"/>'); 
    var img = instances[i].img; 
    img.hide(); 
    img.bind('load', function(e) { 
     var id = parseInt($(this).attr('id').replace('jquery-background-zoom-', '')); 
     instances[id].settings.bg.width = parseInt($(this).width()); 
     instances[id].settings.bg.height = parseInt($(this).height()); 

     $('#debug').html($('#debug').html() + '[' + i + ' ' + instances[id].settings.bg.width + ', ' + instances[id].settings.bg.height + ']<br>'); 
     updateDefaultValues(instances[id]); 

     $(this).remove(); 
    }); 
    $('body').append(img); 
    img.attr('src', instances[i].settings.bg.url); 
} 

var setEvent = function (i) { 
    return function (e) { 
     var inst = instances[$(this).index()]; 
     $('#debug').html(i + ' ' + inst.settings.bg.url); 
     $(this).bind('mousemove', {i:instances[$(this).index()]}, setFollowMouse); 
    } 
} 

var init = function (options) { 

    for (var i = 0; i < this_obj.length; i ++) { 

     instances.push ({id:i, element:this_obj.get(i), settings:$.extend(true, defaults, options)}); 
     instances[i].settings.bg.url = $(this_obj.get(i)).css('background-image').replace('url(', '').replace(')', '').replace(/'/g, '').replace(/"/g, ''); 

     $('#debug').html($('#debug').html() + '<br>' + i + ' -- ' + instances[i].toSource() + '<br><br>'); 

     setImageSize (i); 

     $(instances[i].element).hover(setEvent(i), function() { 
      $(this).unbind('mousemove', setFollowMouse); 
      zoomOut($(this).index()); 
     }); 
    } 
} 

init(); // at the bottom of jQuery plug-in 

私は私が期待するものを手に入れる:event test

({id:0, settings:{url:"http://localhost/js/img/example_0.jpg", other_propos:'relative to the id 0'}}) 
({id:1, settings:{url:"http://localhost/js/img/example_1.jpg", other_propos:'relative to the id 1'}}) 
({id:2, settings:{url:"http://localhost/js/img/example_2.jpg", other_propos:'relative to the id 2'}}) 

私はmousemoveイベントを呼び出したときに、私はなぜ、last element proposしかし右idのみを取得しますか?

({id:0, settings:{url:"http://localhost/js/img/example_2.jpg", other_propos:'relative to the id 2'}}) 
({id:1, settings:{url:"http://localhost/js/img/example_2.jpg", other_propos:'relative to the id 2'}}) 
({id:2, settings:{url:"http://localhost/js/img/example_2.jpg", other_propos:'relative to the id 2'}}) 

ここでは何が欠けているのか分かりませんが、どうすればこの問題を回避できますか?

私はこの問題は、それが本当のwidthheightだ保存するために必要なimg要素background imageを、ロードsetImageSize方法で可能性が疑われます。

ロード遅延が発生する可能性はありますか?

forループで間違った小道具の割り当てについてテストが話しているので、わかりません。

ここはhttp://jsfiddle.net/tonino/CFPTa/問題はjquery loadイベントにあると確信していますが、解決方法はわかりません。

+0

、私は考えていない '$(この).INDEXは()'あなたはそれをやっていると思う何をやっています。その呼び出しを 'i'で置き換えてください –

+0

あなたは何か別のものを表示しています。たとえば、 'element:this_obj.get(i)'がありますが、 'first test'には表示されていません。 '' mousemove '、{i:インスタンスのタイプミス?あなたの例をhttp://jsfiddle.netに移動できましたか? – Cheery

+0

'$(this).index()'は要素の現在のインデックスを返します。最初のインデックスが0の場合は0、2番目のインデックスの場合は以下同様に続きます。これは配列 'instances'のように動作するでしょうか? – vitto

答えて

3

あなたが書いた問題は、閉鎖効果に起因しています。

匿名のホバー機能の中では、i変数を参照していますが、すべての繰り返しが完了するまでそのイベントは呼び出されません。匿名関数内のi変数を参照すると、その時点ではiのコピーはそのままではありません。単純にその参照を使用します。これは、i変数をインクリメントするときに、匿名関数が参照する変数もインクリメントしているので、3回繰り返した後に、作成した3つの匿名関数のすべてが同じiの値を参照していることを意味します:2.

- ことを意味

ファクトリメソッドが呼び出される
var factory = function(i) { 
    return function (e) { 

     var inst = instances[$(this).index()]; 
     // event test, here I get only the last instance propos but the right id, why?? 
     $('#debug').html($('#debug').html() + '<br>' + inst.toSource() + '<br>'); 

     $(this).bind('mousemove', {i:instances[$(this).index()]}, setFollowMouse); // e.data.id 
    } 
} 
for (var i = 0; i < this_obj.length; i ++) { 
    instances.push ({id:i, element:this_obj.get(i), settings:$.extend(true, defaults, options)}); 
    instances[i].settings.bg.url = $(this_obj.get(i)).css('background-image').replace('url(', '').replace(')', '').replace(/'/g, '').replace(/"/g, ''); 

    // first test 
    $('#debug').html($('#debug').html() + '<br>' + instances.toSource() + '<br>'); 

    $(instances[i].element).hover(factory(i), function() { 
     $(this).unbind('mousemove', setFollowMouse); 
     zoomOut($(this).index()); 
    }); 
} 

、返された機能は、それが呼ばれた時に、工場の機能の範囲をキャプチャします:次のように

私は、メソッドのファクトリメソッドを作ることは働くだろうと信じていますi変数は変更されません。

は、より多くの詳細については、この記事を参照してください:http://msdn.microsoft.com/en-us/scriptjunkie/ff696765

+0

これも問題だと思いますが、Jeffの固定コードは4行目の最後の行で 'factory()'に引数を渡しません。それは '私は'そこを通過するべきではない? – btown

+0

ありがとう@btown - now fixed – Jeff

+0

返信ありがとう、私はこのアプローチでコードを変更しましたが、残念ながらこれは私の問題を解決していません。 – vitto

0

は、これは閉鎖に関係しています。ループが完了するまで関数は実行されません。直ちに呼び出される関数を使用してこれを修正できます。

// will awlays output 5 

    for (var i = 0, len = 5; i < len; i += 1) { 
     setTimeout(function() { 
      console.log(i); 
     }, 100); 
    } 

    // this is correct 
    for (i = 0, len = 5; i < len; i += 1) { 
     (function (i) { // notice the immediately invoked function 
      setTimeout(function() { 
       console.log(i); 
      }, 100); 
     }(i)); 
    } 

http://jsfiddle.net/LBahU/

+0

返信いただきありがとうございます。私は自分のコードでこの構文をどのように適用できるかについては分かりませんが、例を書くことはできますか? – vitto

+1

@vittoこの回答は、私の答えにあったものと似ていますが、varにメソッドファクトリメソッドを持つ代わりにインライン展開されています。あなたのケースでそれを行うには、 '.hover(function(i){return function(e){...}}(i)' – Jeff

+0

よろしくお願いします。これは私が他の何かを逃していると思うのと同じことです。 – vitto

関連する問題