2011-08-10 8 views
1

私は約50項目の配列を持っており、javascriptでは条件をチェックするためにこの配列を通過し、条件が満たされればチェックボックスのチェック属性を設定します。それはうまくいっていますが、たびに配列の最後の項目だけを変更します。ここにコードのセクションがあります。条件が満たされた場合Javascriptは配列内の最後の項目の属性のみを設定します

for (i = 0; i < urlArray.length; i++) { 
    var newImg = new Image(); 
    var coName = companyArray[i]; 
    newImg.onload = function(){ 
     if (condition is met){ 
      nStar++; 

        document.getElementById(coName).setAttribute("checked", "checked"); 
        document.getElementById(coName).checked = true; 
     } else { 
      nStar++; 

        document.getElementById(coName).setAttribute("checked", "checked"); 
        document.getElementById(coName).checked = true; 
        document.getElementById(coName).setAttribute("disabled", "disabled"); 
        document.getElementById(coName).disabled = true;   
     } 

    }; 

だから、見ることができるようにするかは、まだ属性を変更しますが、私は受信されているエラーは、それが唯一の配列内の最後の項目を変更することではありません。何か案は?

+0

なぜあなたはsetAttributeと.xxxをやっていますか?彼らはどちらも同じことをする! – epascarello

+0

「条件が満たされました」とは何ですか? – epascarello

+0

haha​​ whoops、私がそれをしたことさえ知らなかった。条件は、URLが正しいドメインかどうかをチェックすることです。 – Calvin

答えて

6

これはJavascriptでの非同期コールバックの古典的な問題です。 onループハンドラは、forループが終了してからしばらくして呼び出されます。したがって、forループのインデックスは最後に固定され、ローカル変数newImgとcoNameはループ内の最後の値のみを持ちます。

onloadハンドラ内で使用したい変数は、実際の関数クロージャに渡す必要があります。これにより、それぞれの異なるonloadハンドラで一意に使用できるようになります。それを行うにはいくつかの方法があります。

この方法では、値に渡されたとのonload関数ハンドラが利用できるようキャプチャする関数クロージャを使用しています。Javascriptを-話すに

for (i = 0; i < urlArray.length; i++) { 
    var newImg = new Image(); 
    var coName = companyArray[i]; 
    newImg.onload = (function (coName) { 
     return function(){ 
      if (condition is met){ 
       nStar++; 
       document.getElementById(coName).setAttribute("checked", "checked"); 
       document.getElementById(coName).checked = true; 
      } else { 
       nStar++; 
       document.getElementById(coName).setAttribute("checked", "checked"); 
       document.getElementById(coName).checked = true; 
       document.getElementById(coName).setAttribute("disabled", "disabled"); 
       document.getElementById(coName).disabled = true;   
      } 
     }; 
    }) (coName); 
} 

を、何このメソッドは行うことはonloadイベントに割り当てされる戻り属性値は無名関数呼び出しを実行しています。その無名関数呼び出しは、coNameパラメータを渡します。この関数は、別の無名関数を返します。これは、onloadハンドラとして割り当てられます。しかし、関数クロージャがjavascriptで動作する方法のために、coNameの値は関数クロージャでキャプチャされ、関数クロージャの持続時間の間、onloadハンドラにアクセス可能に保たれます。 1つは、それが設定されるたびにユニークに捕捉される状態(ローカル変数の値)を持つ関数のインスタンスのようなものです。この場合、coName変数の値をキャプチャし、それが一意になるクロージャに配置し、後でforループにある外側のcoName変数を変更しても影響を受けません。それを行うには

もう一つの方法は、あなたがそこからそれを取り出すことができますので、実際のオブジェクトにパラメータを置くことです:

for (i = 0; i < urlArray.length; i++) { 
    var newImg = new Image(); 
    newImg.setAttribute("coName". companyArray[i]); 
    newImg.onload = function() { 
     var coName = this.getAttribute("coName"); 
     if (condition is met){ 
      nStar++; 
      document.getElementById(coName).setAttribute("checked", "checked"); 
      document.getElementById(coName).checked = true; 
     } else { 
      nStar++; 
      document.getElementById(coName).setAttribute("checked", "checked"); 
      document.getElementById(coName).checked = true; 
      document.getElementById(coName).setAttribute("disabled", "disabled"); 
      document.getElementById(coName).disabled = true;   
     } 

    }; 
} 
0

問題は変数coNameは、常に時間によって最後の配列値になるということですいずれかの機能が実行される。次のようなことができます:

for (i = 0; i < urlArray.length; i++) { 
    var newImg = new Image(); 
    var coName = companyArray[i]; 
    newImg.onload = (function(name){ 
     return function(){ 
      if (true) { 
       nStar++; 
       document.getElementById(name).setAttribute("checked", "checked"); 
       document.getElementById(name).checked = true; 
      } else { 
       nStar++; 

       document.getElementById(name).setAttribute("checked", "checked"); 
       document.getElementById(name).checked = true; 
       document.getElementById(name).setAttribute("disabled", "disabled"); 
       document.getElementById(name).disabled = true; 
      } 
     } 
    })(coName); 
} 
関連する問題