2011-07-04 15 views
0

私はこの種の質問がたくさん聞かれるのを知っていますが、私はまだこの作業を正しく行う方法を見つけることができませんでした。Javascript Closure Problem

コード:

function doStuff() { 
    for (var i = 0; i< elementsList.length; i++) { 
     elementsList[i].previousSibling.lastChild.addEventListener("click", function(){ 
        toggle(elementsList[i])}, false); 


     } 
    } // ends function 


    function toggle (element) { 
     alert (element); 
    } 

問題はトグル機能に変数を渡すことです。このキーワードで動作しますが(これはクリックされた項目への参照を送信しますが、この場合は役に立たない)、Firefoxでは未定義と警告するelementsList [i]では使用できません。

私が理解しているように、関数を呼び出すために匿名関数を使用すると、クロージャの問題に対処するだけで十分です。

+0

の{よりさん}それがさらに2つを持っている...あなたが投稿したコードに問題があるのです。すべてのコードを貼り付けることに失敗しましたか?あなたはあまりにも多く貼り付けたのでしょうか? – Flimzy

+0

dup:http://stackoverflow.com/questions/6492564/webkit-executesql-sentence-and-loop-problem/ http://stackoverflow.com/questions/6495156/jquery-cant-get-my-head-around - この – davin

+0

の可能な複製[Javascript:closure of loop?](http://stackoverflow.com/questions/5555464/javascript-closure-of-loop) –

答えて

3

試してみてください。

function startOfFunction() { 
    for (var i = 0; i< elementsList.length; i++) { 
     elementsList[i].previousSibling.lastChild.addEventListener(
      "click", 
      (function(el){return function(){toggle(el);};})(elementsList[i]), 
      false 
     ); 

    } 
} // ends function 


function toggle (element) { 
    alert (element); 
} 
+1

japrescottが言ったように、イベントで変数iを参照していますハンドラ。これは、イベントハンドラが実行される前に外側のループでさらにインクリメントされます。クロージャを使用することで、変数iはその時点(ループ内)で評価されます。つまり、イベントハンドラの値が固定されていることを意味します。 – Matt

0

試してみてください。

function doStuff() { 
    for (var i = 0; i< elementsList.length; i++) { 
     (function(x) { 
      elementsList[x].previousSibling.lastChild.addEventListener("click", function(){ 
       toggle(elementsList[x])}, false); 
     })(i); 



    } 
} // ends function 

私はそれが周りelementsList[i]を渡すの問題かもしれないと思うので、上記のコードは役立つはず閉鎖を持っています。

1

問題は、var iを使用したいということです。 iはonClickイベントで利用できます(クロージャやもの)。ループがあるので、iがカウントアップされます。ここで、いずれかの要素をクリックすると、iは常にelementsList.lengthになります(すべてのイベント関数は同じiにアクセスするため)。

を使用すると、Mattのソリューションが動作します。

1

説明として:forループで使用する無名関数は、変数 "i"を参照して、要素をトグルするようにします。無名関数は変数の「生きている」値を使用するので、誰かが要素をクリックすると、「i」は常にelementsList.length + 1になります。

Mattのコード例は、iを「固定」されている別の関数に貼り付けることでこれを解決しています。

イベントを添付している要素を反復処理する場合は、単純な匿名関数を使用しないでください。単純な匿名関数を使用しないで、各要素に対して新しい関数を作成してください。 Mattsの答えのより読みやすいバージョンは、次のようになります。

function iterate() { 
    for (var i = 0; i < list.length; i++) { 
     // In here, i changes, so list[i] changes all the time, too. Pass it on! 
     list[i].addEventListener(createEventFunction(list[i]); 
    } 
} 

function createEventFunction (item) { 
    // In here, item is fixed as it is passed as a function parameter. 
    return function (event) { 
     alert(item); 
    }; 
}