2011-10-13 51 views
24

私はアイテムの可変リストを与えられた複数のタイマーを実行しようとしています。コードは次のようなものになります。forループ内でsetInterval関数を使用する方法

var list = Array(...); 

for(var x in list){ 
    setInterval(function(){ 
     list[x] += 10; 
     console.log(x + "=>" + list[x] + "\n"); 
    }, 5 * 1000); 
} 

を上記のコードの問題は、更新されている唯一の値は、リスト内の項目の数を乗じ、リストの末尾のアイテムであるということです。

誰も解決策といくつかの説明を提供できるので、なぜこのように動作するのか知っていますか?

答えて

32

ので、いくつかのこと:それはそれぞれ特定の反復の間に存在していたとして

  1. 最も重要なのは、あなたがsetInterval()に渡されてきたコールバック関数はxへの参照ではなくxのスナップショット値を維持しています。したがって、ループ内でxが変更されると、各コールバック関数内で更新されます。
  2. さらに、for...inはオブジェクトのプロパティを列挙するために使用され、配列で使用される場合はbehave unexpectedlyとなります。
  3. さらに、setInterval()ではなく、setTimeout()が本当に必要だと思われます。

あなたはsetTimout()に追加の引数を供給することによって、あなたのコールバック関数に引数を渡すことができます。

var timeoutID = window.setTimeout(func, delay, [param1, param2, ...]);

はここに例を示します

幸いにも

var list = [1,2,3,4]; 
 

 
for (var x = 0, ln = list.length; x < ln; x++) { 
 
    setTimeout(function(y) {  
 
    console.log("%d => %d", y, list[y] += 10); 
 
    }, x * 500, x); // we're passing x 
 
}

、番号が渡されます値ではなく、参照。ここ

+0

はい、この記事(http://blog.morrisjohns.com/javascript_closures_for_dummies)を読むことをおすすめします。それに加えて、ループ内のsetTimeoutは、コールバックのすべてが同時に起動されるので、彼が何とかしたいとは思っていないかもしれません、それらはずらされません。 – SoWeLie

+0

OPは「閉鎖が必要」ではありません。反対に、回避する必要のある* x *へのクロージャがあります(これは実際には行います)。それは閉鎖を* list *に保ちます。 – RobG

33

作業コードがある:それは連続したループによって上書きされないようにここ

var list = [1, 2, 3, 4, 5]; 

for (var i = 0, len = list.length; i < len; i += 1) { 
    (function(i) { 
     setInterval(function() { 
      list[i] += 10; 
      console.log(i + "=>" + list[i] + "\n"); 
     }, 5000) 
    })(i); 
} 

指数iは、匿名関数に格納されています。コード内のsetInterval関数は、参照を最後の値のiにのみ保持します。

+0

良い解決策! –

+0

優れたソリューション!小さなノート:ループ内で変更できるものは、インデックスだけでなく、無名関数に渡すことができます。 –

2

setIntervalステートメントでforサイクルを使用する必要はありません。あなたはJSONの配列を持っているとjQueryが含まれている場合は、使用することができます

var list = Array(...); 
var x = 0; 

setInterval(function() { 

    if (x < list.length;) { 
     list[x] += 10; 
     console.log(x+"=>"+list[x]); 
    } 

    else return; 

    x++; 
}, 5000); 
0

:これを試してみてください

$.each(jsonArray, function(i, obj) { 
    setInterval(function() { 
     console.log(i+' '+obj); 
    }, 10); 
}); 
2

私はforループでこれを行う方法を知りませんが、ここで、このコードが印刷されます配列内の各要素は、時間間隔で配列されます。

function displayText(str) { 
    $('.demo').append($('<div>').text(str)); 
} 
var i = 0; 

var a = [12, 3, 45, 6, 7, 10]; 

function timedLoop() { 
setTimeout(function() { 
    displayText(a[i]); 
    i++; 
    if(i < a.length) { 
     timedLoop(); 
    } 
}, 2000) 
} 

timedLoop(); 

jqueryを使用してブラウザに表示します。

関連する問題