75

JavaScript ステートメント (Chrome のコンソール内) が 1 ミリ秒で変数を何回whileインクリメントできるか疑問に思ったので、すぐにこのスニペットをコンソールに直接書きました:

var run = true, i = 0;
setTimeout(function(){ run = false; }, 1);
while(run){ i++; }

問題は、それが永久に実行されることです。
なぜこれが起こっているのですか、どうすれば解決できますか?

4

6 に答える 6

80

これは、JavaScript 1の 1スレッドの性質に戻ります。何が起こるかは、ほとんどこれです:

  1. 変数が割り当てられます。
  2. 機能をスケジュールして、 を設定しrun = falseます。これは、現在の関数が実行された後に実行されるようにスケジュールされています (または現在アクティブになっているものは何でも)。
  3. 無限ループがあり、現在の関数内にとどまります。
  4. 無限ループ ( never ) の後、setTimeout()コールバックが実行されrun=falseます。

ご覧のとおり、setTimeout()アプローチはここでは機能しません。条件の時間を確認することで回避できwhileますが、実際の測定値が改ざんされます。

1少なくともより実用的な目的では、シングルスレッドと見なすことができます。実際には、いわゆる「イベントループ」があります。そのループでは、すべての関数が実行されるまでキューに入れられます。新しい関数をキューに入れると、そのキュー内のそれぞれの位置に配置されます。現在の関数が終了したsetTimeout()、エンジンはキューから次の関数を取得し (たとえば、導入されたタイミングに関して)、それを実行します。
その結果、すべての時点で関数が 1 つだけ実行されるため、実行がきれいになります。イベントには例外がいくつかありますが、これについては以下のリンクで説明しています。


参考のため:

于 2014-02-09T08:10:35.163 に答える
24

JavaScript はシングル スレッドであるため、ループ中は他に何も実行されません。

于 2014-02-09T08:11:24.627 に答える
19

速度を計算するために常に時間を取得しなくても Chrome の真の速度を維持するには、次の JS コードを試すことができます。

var start = new Date().getTime()
var i = 0
while(i<1000000)
{
    i++
}
var end = new Date().getTime()
var delta = end-start
var speed = i/delta
console.log(speed + " loops per millisecond")
于 2014-02-09T13:29:39.730 に答える
4

Javascript はシングルスレッドです。つまり、一度に 1 つの命令のみを順番に実行します。

イベント システムは、他の多くの言語やライブラリと同様に、イベント ループによって処理されます。イベント ループは基本的にループであり、反復ごとにキュー内のメッセージをチェックし、イベントをディスパッチします。

JavaScript では (このパターンを実装する言語の mot のように)、イベント ループはスタックが空になると呼び出されます。

「実際の」プログラムは、舞台裏で次のようになります。

var run = true, i = 0;
setTimeout(function(){ run = false; }, 1);
while(run){ i++; }

while(true) {
/*
 * check for new messages in the queue and dispatch
 * events if there are some
 */
  processEvents();
}

そのため、タイムアウトが終了したという時計からのメッセージは処理されません。

イベントループの詳細: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/EventLoop


もちろん、もう少し複雑です。ここで例を確認してください( tl;dr:一部のブラウザー エンジンでは、一部の外部イベントはイベント ループに依存せず、発生するとすぐに起動され、現在のタスクがプリエンプトされます。しかし、キューにメッセージを追加するだけの setTimeout の場合はそうではありませんすぐに発火することはありません。)

于 2014-02-09T15:16:30.047 に答える
2

While ループは setTimeout にアクセスしません。run true を設定するコードがあり、その後 false になることはありません。

于 2014-02-09T20:06:28.583 に答える
1

JavaScript にはシングル スレッドがあり、どこでもシングル スレッドです。

この質問は良いと思います: JavaScript はシングルスレッドであることが保証されていますか?

コードがループしている場合、他の ocde は実行およびブロックされません。

于 2014-02-10T04:31:21.107 に答える