1

ここで私がやろうとしていること。私は次のような配列を持っています

var my_array = ['1', '2', '3' ... ,'1000000000000000'];

私がやりたいのは、その配列のすべての要素に対して一連の HTML 要素を作成することです。配列には膨大な数の要素が含まれている可能性があるため、ブラウザーがフリーズしないように次のことを試みました。

for(var i in my_array)
{
    if(my_array.hasOwnProperty(i))
    {
       setTimeout(function(){
             do_something_with_data(my_array[i]);
       });
    }
 }

ただし、setTimeout 内の my_array[i] に必要な値がありません。

より正確にconsole.log(my_array[i])言うと、私が得ようとすると、次のようになります。

"getUnique" function (){
   var u = {}, a = [];
   for(var i = 0, l = this.length; i < l; ++i){
      if(u.hasOwnProperty(this[i])) {
         continue;
      }
      a.push(this[i]);
      u[this[i]] = 1;
   }
   return a;
}

getUnique は、次のように Array プロトタイプに追加した関数です。

Array.prototype.getUnique = function(){
   var u = {}, a = [];
   for(var i = 0, l = this.length; i < l; ++i){
      if(u.hasOwnProperty(this[i])) {
         continue;
      }
      a.push(this[i]);
      u[this[i]] = 1;
   }
   return a;
};

誰かがこの問題について私を助けてくれますか?

4

3 に答える 3

3

setTimeout はループが終了した後に実行され、iその時点での最後のキーまたはガベージ値です。i like を次のようにキャプチャできます。

for (var i in my_array) {
    if (my_array.hasOwnProperty(i)) {
        (function(capturedI) {
            setTimeout(function() {
                do_something_with_data(my_array[capturedI]);
            });
        })(i);
    }
}

また、配列にループを使用しないでください。これは、for ループよりも 1for..in桁遅く (特に.hasOwnPropertyチェックの場合)、反復順序が定義されていないためです。

jQuery をお持ちの場合、または古いブラウザー用にコードを追加したい場合は、次のことができます。

my_array.forEach( function( item ) {
     setTimeout( function() {
         do_something_with_data( item );
     }, 1000);
});

jQuery の場合:

$.each( my_array, function( index, item ) {
     setTimeout( function() {
         do_something_with_data( item );
     }, 1000);
});

ドキュメントを参照してください[].forEach

于 2012-11-28T15:04:50.490 に答える
2

問題は、作成している関数がそののコピーではなく、変数への参照を持っているため、実行すると、その時点での状態がそのまま表示されることです (おそらく、配列の末尾を過ぎて)。(詳細:閉鎖は複雑ではありません)ii

まったく別のアプローチ (以下) をお勧めしますが、まず、既存のアプローチを機能させる方法を見てみましょう。

あなたがやろうとしていたことをforループで行うには、変更されない何かを関数で閉じる必要があります。これを行う通常の方法は、ファクトリへの引数を閉じるようにタイムアウト関数を作成するファクトリ関数を使用することです。または、実際には、インデックス変数ではなく、配列要素の値を渡すことができます。

for(var i in my_array)
{
    if(my_array.hasOwnProperty(i))
    {
       setTimeout(makeFunction(my_array[i]));
    }
 }

function makeFunction(entry) {
    return function(){
        do_something_with_data(entry);
    };
}

しかし、おそらくコードを再構築して、関数オブジェクトの塊と塊を不必要に作成しないようにします。代わりに、1 つの関数を使用し、インクリメントするインデックスを閉じるようにします。

// Assumes `my_array` exists at this point, and that it
// has at least one entry
var i = 0;
setTimeout(tick, 0);
function tick() {
    // Process this entry
    if (my_array.hasOwnProperty(i)) {
        do_something_with_data(my_array[i]);
    }

    // Move to next
    ++i;

    // If there are any left, schedule the next tick
    if (i < my_array.length) {
        setTimeout(tick, 0);
    }
}
于 2012-11-28T15:04:35.950 に答える
0

それはただの推測です。次のように試してください:

for(var i in my_array)
{
    if(my_array.hasOwnProperty(i))
       setTimeout("do_something_with_data('"+my_array[i]+"')", 500);
}
于 2012-11-28T15:04:38.380 に答える