for(var i=1;i<5;i){setTimeout(function(){console.log(i)},i*1000);}For ループはここにありますが最初に完了しますその後、i の値は 5 になりますその後、for ループが最初に実行されるのに、なぜ i*1000 が実行されるのですか
for ループが実行されるとき、それはページ内に 4 つのタイマー関数を記述することと同じであり、この時点ではタイマー関数はまだ実行されておらず、タイマー時間の時点でグローバルの i 変数の値は 5 です。が終了すると、タイマー機能が 4 つ 5 つ順番に実行されます。
この例はクロージャではありません。クロージャは次のように記述する必要があります。これは、ページ上ですぐに実行される 4 つの関数を記述することと同じであり、これらの 4 つの関数が受け取る実際のパラメータは、順番に 1、2、3、4 です。クロージャーの特徴によると: タイマーが終了すると、タイマー関数は外部関数によって受け取られた実際のパラメーターにアクセスできるため、1、2、3、4 を順番に出力します
コンピューターでは、変数はすべてメモリ内にスペースを空けて保存する必要があり、その後、すべての変数にアドレスが割り当てられます。 C言語やアセンブリ言語を勉強したことがある人なら、このことをよく知っているはずです。
まず、なぜ毎回 5 を出力するのかについて話しましょう。 i の空間 (つまり、i を格納するために使用されるメモリ空間、学術的には「スタック」と呼ばれます) は 5 回変更されており、匿名関数が実行されると、i の空間には 5 が格納されるためです。
2 番目のパラメータが毎回異なる理由を説明しましょう。 i*1000并没有修改i的值,而是会产生一个结果。那么这个结果必然要找地方去存。存储在哪呢?setTimeout每被调用一次,都会开辟一段内存空间,其中一部分空间就用于存储它的两个参数。其中一个参数就是刚才i*1000产生的结果。而setTimeout被调用了5次,于是存储了5个结果!没错,是在5个不同的空间存储了5个结果,而不是像i同じスペースが5回変更されました!ご想像のとおり、このアプローチは非常にメモリを大量に消費します。
i*1000
i
setTimeout
この説明理解できますか?
for 関数がメインスレッドに入ると、各 setTimeout は順番にタスクキューに入り、for が実行された後、タスクキュー内の setTimeout が実行のためにメインスレッドに入ります。クロージャがない場合、setTimeout が実行されるとき i はすでに 5 ですが、クロージャがある場合、i の値は setTimeout がタスク キューに入るときに保存されます。 参照: イベントループ
for ループが実行されるとき、それはページ内に 4 つのタイマー関数を記述することと同じであり、この時点ではタイマー関数はまだ実行されておらず、タイマー時間の時点でグローバルの i 変数の値は 5 です。が終了すると、タイマー機能が 4 つ 5 つ順番に実行されます。
この例はクロージャではありません。クロージャは次のように記述する必要があります。これは、ページ上ですぐに実行される 4 つの関数を記述することと同じであり、これらの 4 つの関数が受け取る実際のパラメータは、順番に 1、2、3、4 です。クロージャーの特徴によると: タイマーが終了すると、タイマー関数は外部関数によって受け取られた実際のパラメーターにアクセスできるため、1、2、3、4 を順番に出力します
リーリーコンピューターでは、変数はすべてメモリ内にスペースを空けて保存する必要があり、その後、すべての変数にアドレスが割り当てられます。 C言語やアセンブリ言語を勉強したことがある人なら、このことをよく知っているはずです。
まず、なぜ毎回 5 を出力するのかについて話しましょう。 i の空間 (つまり、i を格納するために使用されるメモリ空間、学術的には「スタック」と呼ばれます) は 5 回変更されており、匿名関数が実行されると、i の空間には 5 が格納されるためです。
2 番目のパラメータが毎回異なる理由を説明しましょう。
i*1000
并没有修改i
的值,而是会产生一个结果。那么这个结果必然要找地方去存。存储在哪呢?setTimeout
每被调用一次,都会开辟一段内存空间,其中一部分空间就用于存储它的两个参数。其中一个参数就是刚才i*1000
产生的结果。而setTimeout
被调用了5次,于是存储了5个结果!没错,是在5个不同的空间存储了5个结果,而不是像i
同じスペースが5回変更されました!ご想像のとおり、このアプローチは非常にメモリを大量に消費します。この説明理解できますか?
for 関数がメインスレッドに入ると、各 setTimeout は順番にタスクキューに入り、for が実行された後、タスクキュー内の setTimeout が実行のためにメインスレッドに入ります。クロージャがない場合、setTimeout が実行されるとき i はすでに 5 ですが、クロージャがある場合、i の値は setTimeout がタスク キューに入るときに保存されます。
参照: イベントループ