1

現在、私は RaphealJS ライブラリを使用するプロジェクトに取り組んでおり、このような問題が発生するまではすべて問題ないようです。

これを複数回行う代わりに:

   dolphinIcon[1].click(function() {              
           this.attr({  
             stroke: 'black', 'stroke-width': 2,  
             fill: 'green'  
           }); 
           alert(1);
   });

   dolphinIcon[2].click(function() {              
           this.attr({  
             stroke: 'black', 'stroke-width': 2,  
             fill: 'green'  
           }); 
           alert(2);
   });

  dolphinIcon[3].click(function() {              
           this.attr({  
             stroke: 'black', 'stroke-width': 2,  
             fill: 'green'  
           }); 
           alert(3);
   });

なぜ私はこれを行うことができないのですか?

for(var i=0; i<dolphinIcon.length; i++){
     dolphinIcon[i].click(function() {              
        this.attr({  
           stroke: 'black', 'stroke-width': 2,  
           fill: 'green'  
        });      
        alert(i);
     });
}

配列に格納されている各アイコンにそのインデックスの数をアラート()させたいだけですが、forループを使用すると、どのアイコンをクリックしても常に同じ数(配列のサイズ)をアラート()します. これを修正するにはどうすればよいですか?

4

5 に答える 5

5

これは古典的な JavaScript の問題です。i各コールバック関数の変数は同じでdolphinIcon.length、ループが完了すると同じになります。

i変数を「キャプチャ」するには、クロージャを使用する必要があります。

var clickFunc = function(i){
    return function(){
        this.attr({  
           stroke: 'black', 'stroke-width': 2,  
           fill: 'green'  
        });      
        alert(i);
    }
};
for(var i=0; i<dolphinIcon.length; i++){
     dolphinIcon[i].click(clickFunc(i));
}

clickFuncの値を「閉じる」関数を返しますi

追加のデータをclickハンドラーに渡して、呼び出されたときに使用することもできます。

for(var i=0; i<dolphinIcon.length; i++){
     dolphinIcon[i].click({i: i}, function(e) {              
        this.attr({  
           stroke: 'black', 'stroke-width': 2,  
           fill: 'green'  
        });      
        alert(e.data.i);
     });
}
于 2012-09-19T20:45:25.517 に答える
3

これは、javascript クロージャーの仕組みによるものです。基本的に、コールバック/イベント処理関数は、ループの連続する繰り返しで i の特定の値ではなく、ループ変数 i にバインドされます。

簡単な回避策は次のとおりです。ループの内部を無名関数でラップし、ループ変数をその関数に渡します。これにより、クロージャーがその特定の値にアタッチされます。

例えば:

for(var i=0; i<dolphinIcon.length; i++)
{
    (   function(i) 
        {
            dolphinIcon[i].click(function() 
            {              
                this.attr({ stroke: 'black', 'stroke-width': 2, fill: 'green'});      
                alert(i);
            } );
        } )( i );
}
于 2012-09-19T20:46:11.607 に答える
2

これを試して:

for(var i=0; i<dolphinIcon.length; i++){ 
     dolphinIcon[i].bind('click', {index: i}, function(e) {             
        $(this).attr({   
           stroke: 'black', 'stroke-width': 2,   
           fill: 'green'   
        });       
        alert(e.data.index); 
     }); 
}
于 2012-09-19T20:46:34.433 に答える
0

underscore.js ライブラリを提案したいと思います。配列と onbject を処理するための多くのユーティリティ メソッドが含まれています (あなたの場合は each と bind) http://underscorejs.org/#each

あなたの例では、このコードは次のように縮小されます。

_.each(dolphicons, function(dolphicon, index){  
    var func = function() {              
        this.attr({  
           stroke: 'black', 'stroke-width': 2,  
           fill: 'green'  
        });      
        console.log(index);
    }
    func = _.bind(func, dolphicon);

    dolphicon.click(func);
});

「これ」は、バインドされているため、ドルフィコンを指します。例も: http://jsfiddle.net/SyJdv/

各ループの外で関数をスコープすることもできます

var func = function() {              
   this.obj.attr({  
      stroke: 'black', 'stroke-width': 2,  
      fill: 'green'  
    });      
    console.log(this.index);
}

_.each(dolphicons, function(dolphicon, index){  
   var clickfunc = _.bind(func, {obj: dolphicon, index: index});    
   dolphicon.click(clickfunc);
});

http://jsfiddle.net/PW9WX/1/

于 2012-09-19T21:26:14.337 に答える