概要まず、setTimeout 遅延の動作メカニズムを簡単に見てみましょう。 setTimeout は、まずコールバック関数を待機キューに配置し、待機領域にある他のメイン プログラムが実行された後、コールバック関数を時系列順に実行します。それは本質的には範囲の問題です。 したがって、これを実行すると、目的の出力 1.2.3.4.5 は得られず、5 つの連続した 6 が出力されます。 (var i=1; i<=5; i++) の場合 { setTimeout(関数タイマー() { コンソールにログ出力します。 }, i*1000 ); } これは、setTimeout が非同期で実行されるためです。for ループが実行されるたびに、setTimeout は 1 回実行されますが、内部の関数は実行されません。代わりに、タスク キューに配置され、実行を待機します。メインライン上のタスクが完了した場合にのみ、タスクキュー内のタスクが実行されます。つまり、 for ループが完全に終了するまで待機してから fun 関数を実行します。ただし、 for ループが終了すると、 i の値は 6 になっています。そのため、タイマーは 5 秒間実行されますが、コンソールの内容は 6 のままです。 (注: for ループは、開始から終了まで数マイクロ秒または数ミリ秒続く必要があります。タイマーが 1 秒経過すると、for ループはすでに完了しています。) 別のケースを見てみましょう。 (var i=1; i<=5; i++) の場合 { (関数() { setTimeout(関数タイマー() { コンソールにログ出力します。 }, i*1000 ); })(); } setTimeout の動作メカニズムから、すべての外部メイン プログラムが最初に実行されることがわかります。for ループではクロージャが形成されますが、fun は実際のパラメーターを見つけないため、最初の例と実際の違いはなく、5 つの連続した 6 が引き続き出力されます。 解決策 1: クロージャクロージャを使用するのは古典的なアプローチです。 (var i=1; i<=5; i++) の場合 { (関数(j) { setTimeout(関数タイマー() { コンソールログ(j); }, j*1000 ); })(私); } 予想される結果は、1 から 5 までの順番の出力と一致していることがわかります。これは、実際のパラメータがタイマー内の i に強く依存しているためです。 クロージャを通して、変数 i がメモリ上に常駐します。j が出力される際、外部関数の変数値 i が参照されます。i の値はループに基づいており、setTimeout が実行されると内部の出力が決定されます。 解決策2: 構造を分割するsetTimeout の定義と呼び出しを別の部分に分けることもできます。 関数タイマー(i) { タイムアウトを設定します( console.log( i ), i*1000 ); } (var i=1; i<=5; i++) の場合 { タイマー(i); } コンソールの出力は、引き続き 1 から 5 の順になっています。 解決策3:es6 の let を使用してこの問題を解決する別の方法を次に示します。 (i=1; i<=5; i++) の場合 { setTimeout(関数タイマー() { コンソールにログ出力します。 }, i*1000 ); } 最初の例と比較すると、この例では var が let に変更されるだけですが、コンソールには 1 から 5 が順番に出力されます。 for ループの先頭にある let は i を for ループにバインドするだけでなく、実際にループ本体の各反復に再バインドし、前の反復の終了時の値が再割り当てされるようにします。 setTimeout の function() は新しいスコープに属します。var で定義された変数は、この関数の実行スコープに渡すことはできません。let を使用してブロック変数を宣言すると、このブロックで動作できるため、function は変数 i を使用できます。この匿名関数のパラメーター スコープは for パラメーターのスコープとは異なりますが、これは this を利用して実現されています。この匿名関数のスコープはクラスの属性に多少似ており、内部メソッドで使用できます。 解決策4: setTimeoutの3番目のパラメータ(i=1; i<=5; i++) の場合 { setTimeout(関数タイマー() { コンソールにログ出力します。 }, i*1000, i ); } 毎回渡されるパラメータはforループから取得した値なので、1~5が順番に出力されます。 上記は、JS の for ループで setTimeout を使用するための 4 つのソリューションの詳細です。JS で setTimeout を使用する方法の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。 以下もご興味があるかもしれません:
|
>>: Docker での RocketMQ の詳細なインストールと使用
ソースコードの例: https://codepen.io/shadeed/pen/03caf6b36...
目次js 呼び出しメソッドアンドロイド1.jsはネイティブを呼び出す2. ネイティブコールjs iO...
目次1.1Tinyint型の説明1.2 練習環境の説明1.3 未署名属性の追加1.3.1 SQLモー...
目次1. サービスの開始と停止の手順1.1 Windows での MySQL 5.7 の公式 MSI...
A. MySQLバックアップツールxtrabackupのインストール1. Percona 公式 xt...
1. まずmysqld.exeプロセスを停止します2. cmd を開き、mysql の bin ディ...
MySQL のログには、エラー ログ、バイナリ ログ、一般クエリ ログ、スロー クエリ ログなどが含...
序文プロジェクト要件: Dockeridea に Docker プラグインをインストールし、Dock...
目次1. テーブル名を変更する方法2. 注記要約: 1. テーブル名を変更する方法RENAME TA...
カルーセル主なアイデアは次のとおりです。大きなコンテナには、コンテナの幅の整数倍の非常に長いテーブル...
目次1. コンポーネント2. キープアライブ2.1 問題点2.2 キープアライブを使って解決する2....
RabbitMQをインストールする前にSocatをインストールする必要があります。そうしないと、Ra...
事前に言っておくNodejs はデータベースを非同期操作として読み取るため、データベースがデータを読...
目次序文関数のオーバーロードマッピングタイプ部分的、読み取り専用、Null 可能、必須選択、記録除外...
DOCTYPE 宣言 作成するすべてのページの先頭に、ドキュメント宣言が必要です。はい、そうでしょう...