2010-12-10 16 views
1

私はこのようなコードを使用して、イベントハンドラ関数に引数を渡します。しかし、この特定のケースでは、ループが問題を引き起こしています。すべてのactiveVisual呼び出しで最後のlinkTags [i]だけがアクセス可能です。これは、引数を渡す無名関数がループ全体に対して同じであるという事実と関係しています。addEventListenerに "新しい"匿名関数を渡すことができます

for (var i = 0; i < linkTags.length; i++) { 
    addCrossEvent(linkTags[i], "click", launchLink); 
    addCrossEvent(linkTags[i], "mousedown", 
     function(evt) { 
     activeVisual(evt, linkTags[i]); 
     }); 
    } 

は今、私はこのような無名関数宣言の前に新しいを追加しようと覚えている:

for (var i = 0; i < linkTags.length; i++) { 
    addCrossEvent(linkTags[i], "click", launchLink); 
    addCrossEvent(linkTags[i], "mousedown", 
     new function(evt) { 
     activeVisual(evt, linkTags[i]); 
     }); 
    } 

それは動作しませんでした。 activeVisualは決して呼び出されません。なぜ誰かに私に説明することができますか、どうすればそれを動作させることができますか?

UPDATE FINAL SOLUTION

私WORKINGコードの下にあるすべての回答のおかげで次のようになります。

// Function that provides pass of event handling parameters with separate copy in each loop 
    function callbackHandler(index) { 
    return function(evt) { 
     activeVisual(evt, linkTags[index]); 
    } 
    } 
    ... 
    for (var i = 0; i < linkTags.length; i++) { 
    ... 
    addCrossEvent(linkTags[i], "mousedown", callbackHandler(i)); 
    } 

答えて

5

あなたがこれを実行する必要があります。

addCrossEvent(linkTags[i], "mousedown", 
     (function(i) { 
      return function(evt) { 
       activeVisual(evt, linkTags[i]); 
      } 
    )(i); 
); 

問題がイテレータであります各反復で変化する変数iがあり、参照が渡されると、iの値はコピーされません。これをラッパー関数のパラメーターとしてこのように渡すと、コピーが発生し、その特定の反復で実際の値を受け取ります。

あなたはnewで関数を呼び出し、関数は、関数の内部でthisで参照することができ、空のオブジェクトを(生成:完全性については

+0

。 ?それは匿名の関数にのみ言い渡されていますか? –

+1

addCrossEvent(linkTags [i]、 "click"、launchLink)を実行すると、あなたは各ループのlinkTags配列に値iを持っていますが、関数がイベントで呼び出されると、最後の値があり、配列内の同じ位置になります。 – madeinstefano

+1

@ avok00: 'addCrossEvent(linkTags [i ]、 "click"、launchLink) '' linkTags [i] 'の値を直接関数に渡します。しかし、* callback *内の 'activeVisual(evt、linkTags [i]);'は、コールバックが呼び出されたときに評価されます。しかし、コールバックが呼び出されると、ループは既に終了しており、 'i'はその最終値を持っています。 –

2

は、ここnewを使用してのあなたの方法がうまくいかない理由の説明です関数のプロトタイプから継承したもの)を返します。
実際には、関数をコールバックハンドラとして渡すのではなく、関数が返すオブジェクトを渡します。

オブジェクトがイベントハンドラとして使用できるようにEventListner interfaceを実装している限り、問題はありません。あなたがこれを行う場合は、いくつかの変更であなたのコードを使用することができます。

for (var i = 0; i < linkTags.length; i++) { 
    addCrossEvent(linkTags[i], "click", launchLink); 
    addCrossEvent(linkTags[i], "mousedown", 
     new (function(index) { 
     this.handleEvent = function(evt) { 
      activeVisual(evt, linkTags[index]); 
     } 
     })(i)); 
    } 

iの値は、オブジェクトの作成時にキャプチャされるので、これは、実際にはルカの答え@に似ています。私は読み機能を簡単に返す即時関数の使い方を見つけて、私はオブジェクトではなくイベントハンドラとしての機能を使用して考えて、あまりにも多く見られた

function CallbackHandler(index) { 
    this.handleEvent = function(evt) { 
     activeVisual(evt, linkTags[index]); 
    } 
} 

for (var i = 0; i < linkTags.length; i++) { 
    addCrossEvent(linkTags[i], "click", launchLink); 
    addCrossEvent(linkTags[i], "mousedown", new CallbackHandler(i)); 
} 

:上部のコードは、実際に同じです。変数iイテレータは、その行addCrossEvent(linkTags [i]は、「クリック」、launchLink)で問題が発生しないことを来るどのように問題がある場合は

Working DEMO

+0

+1非常に良い解決策と説明のために。申し訳ありませんがIE8で動作しない可能性がありますthis.handleEventを理解していない可能性があります:( –

+0

@ avok00:多分... IEは常に特別です;)しかし、理由は、 'event'オブジェクトがIEで異なって検索されます。イベントの処理とブラウザ間の問題については、http://www.quirksmode.org/js/introevents.htmlを参照してください。 –

関連する問題