forループのsetTimeoutを使用しています
のは、setTimeoutを遅延の動作機構を簡単に見てみましょう。コールバック関数へのsetTimeoutは、最初に別のメインプログラムの待機を時系列にコールバックFIFO領域を行って、終了し、キューをお待ちしております。本質的に問題の範囲があります。
したがって、もしこれが1.2.3.4.5出力は、所望の結果を取得し、連続出力5 6わけではないであろう。
ため(VAR I = 1; I <= 5; I ++ ){ のsetTimeout(関数タイマー(){ にconsole.log(I); }、iは 1000 * )。 }
これは、各サイクルタイムのために、setTimeoutを一回実行されますが、実行すべき機能がないが、実行されるのを待って、タスクキューに入れた後のsetTimeoutは、非同期であるためです。実行メインライン上のタスクのみ、タスクキューのタスクを実行します。終わりがループのため、この時点でのiの値が6になった場合には、タイマーが5秒を走ったので、にもかかわらず、コンソール上のコンテンツを、それが全体のサイクルの実行が終了した後、関数funを実行しますまで待つであろうが、それはまだ6です。
(注:最初からループのためのプロセスの最後に、タイマーがすでに行わループの後に1秒を実行したときに、数マイクロ秒またはミリ秒を維持する必要があります。)
私たちは、別のシナリオを見て続行します。
ため(VAR I 1 =; I <= 5; I ++ ){ (関数(){ のsetTimeout(関数タイマー(){ にconsole.log(I); }、iは 1000 * ); })(); }
操作機構でのsetTimeoutは、それはまだ連続出力5で最初の例とは実質的な違いはありませんので、内側のループのため閉鎖の形成が、楽しみは、引数を見つけられませんでしたが、最初にすべてのメインプログラムが、外で実行されます、知っているかもしれません6ヶ月。
解決策1:クロージャ
別の例を見て続行します。
ため(VAR I 1 =; I <= 5; I ++ ){ (関数(J){ のsetTimeout(関数タイマー(){ にconsole.log(J); }、J ×1000 ); })(I)。 }
我々の調査結果は、内部タイマの実際のパラメータは、私は強い依存性を持っているので、結果で、1-5の出力回すことができる期待される結果と一致しています。
出力jは、iの値に応じて実行されるのsetTimeout出力を内部で決定されたサイクルは、ある変数i外部関数の基準値である場合に閉鎖することにより、変数iが、メモリに常駐しています。
解決策2:分割構造
もう一つは、のさまざまな部分に置かれたのsetTimeoutを定義して呼び出すことです。
機能タイマ(I){ たsetTimeout(にconsole.log(I)、私は 1000 * )。 } ため(VAR I 1 =; I <= 5; I ++ ){ タイマ(I)。 }
コンソール出力に依然として1-5順次出力されます。
解決策3:みましょう
ここで再び、この問題を解決するために使用についてES6話をしてみましょう:
以下のために(iは1 =せ; I <= 5; I ++ ){ のsetTimeout(関数タイマー(){ にconsole.log(I)を }、iは 1000 * )。 }
この例では、最初に比べて、ちょうどvarはLETになった変更が、コンソールの結果は、ターン出力1-5です。
letが、私はループのために、それは実際には、ループの各反復に再バインドされますにバインドされる頭部の循環のためだけでなくので、前回の反復終了の値が再割り当てていることを確認してください。新しいドメインに属している関数内でのsetTimeout()は、変数は変数のletブロックは、このブロック内で機能することができ宣言使用してこの機能ドメインの実行に渡されたvarで定義されていない、関数は、この変数iを使用することができますまで;引数無名関数のスコープと範囲のパラメータが同じではありません、完了するためにこの利点です。この範囲匿名関数幾分類似クラスのプロパティ、内側層を使用することができる方法です。
解決策4:のsetTimeout三番目のパラメータ
以下のために(iは1 =せ; I <= 5; I ++ ){ のsetTimeout(関数タイマー(){ にconsole.log(I)を }、私は 1000 * 、I)。 }
各パラメータは、forループから採取された値に渡されるように、1-5を出力になります。setTimeoutを第三引数について、次はここで、我々は次のように理解し、詳細にについて話します。