2016-12-03 22 views
0

スクリプトです:奇妙な結果

for(var i = 0; i < 5; i++) { 
    setTimeout(function() { console.log(i); }, 0); 
}; 

コンソールで理論的には、出力すべきちょうど5「5」。しかし、Chrome、Opera、またはSafariのコンソールで実行すると、奇妙な数字が残っています。 OSはmacOS Sierra 10.12.1です。

など。

クローム54.0.2840.98(64ビット):

for(var i = 0; i < 5; i++) { 
     setTimeout(function() { console.log(i); }, 0); 
    }; 
2105 
⑤ 5 

サファリ10.0.1:

> for(var i = 0; i < 5; i++) { 
     setTimeout(function() { console.log(i); }, 0); 
    }; 
< 6 
> for(var i = 0; i < 5; i++) { 
     setTimeout(function() { console.log(i); }, 0); 
    }; 
< 11 
> for(var i = 0; i < 5; i++) { 
     setTimeout(function() { console.log(i); }, 0); 
    }; 
< 16 

オペラ39.0:

for(var i = 0; i < 5; i++) { 
     setTimeout(function() { console.log(i); }, 0); 
    }; 
5 
⑤ 5         VM73:2 
for(var i = 0; i < 5; i++) { 
     setTimeout(function() { console.log(i); }, 0); 
    }; 
10 
⑤ 5         VM74:2 

あなたはそれを自分で試みることができます。興味深いのは、HTMLページに含まれる同じコードが必要なように動作することです。コンソールが開いているタブによって、番号が異なります。それは何ですか?サイクルのための何らかの内部カウンタを推測しますが、わかりません。別の考え方 - コンソールは、関数の戻り値を実行するものを示します。おそらくそれはそうです。しかし、forは何も返しません。少なくともそれはすべきではない。同じコードだが、setTimeoutがないと、奇妙な数字の代わりにundefinedが表示されます。たぶん誰かがそれについて私とインターネットよりも少し知っています。どんな考えも高く評価されています。私の英語には申し訳ありません。ありがとうございました!

+0

同じスコープ内の変数を制限するために 'var'の代わりに' let'を使用してください。 – Endless

+0

[ループ内のJavaScriptクロージャーの可能な複製 - 簡単な実用的な例](http://stackoverflow.com/questions/750486/) – Endless

+0

クロムとオペラの例では、2105は 'setTimeout'コールの結果として得られる最後のタイマーです。 「⑤5」は、「5」という数字が明らかに5回出力されたことを意味する。 SafariはタイマーIDも表示しているようですが、なぜiが出力されないのかわかりませんが、おそらくコンソール設定の問題です。 –

答えて

2

ここでは、最小限の例です:

for(var i = 0; i < 5; i++) setTimeout(function() {}) 
> 71 (or whatever) 

文が値を持っていませんが、コンソールが「役に立つ」になろうとし、最後に評価式が返されたものを出力 - この場合は返すsetTimeout(...)ですタイムアウトID - 任意の数。

+0

あなたは正しいかもしれませんが...このコードを順番に実行してみてください。 75、80、85、90、95、100など...(基本的に5(サイクル反復回数))増加するので、この数値は何か面白いのですか? –

+0

@ Serj.by:タイムアウトIDが順番に割り当てられているように見えるので、コードは5つのタイムアウトを割り当て、最後のIDを返します。混乱を避けるために "random"を "arbitrary"に編集しました;) – georg

1

戻り値はsetTimeoutから出力されている可能性があります。これは、clearTimeoutを使用してクリアするために使用できます。これをもう一度実行すると、各タイムアウトに固有の番号があるため、別の値が返されます。

一方、あなたはおそらく、それが同様に実際のログを見るために、すべてのを示し、それを変更のみエラーを表示するには、コンソールをフィルタリングしています。 DevToolsにはのエラーしかありません。 (Safari)

+0

答えをありがとう! 'clearTimeout'はただちにタイムアウトを破棄しますが、実行に時間がかかるので何も実行されません。 (var i = 0; i <5; i ++){ } clearTimeout(to); } 未定義 おそらくあなたは何か言及しましたか?しかし、タイムアウトをクリアすると、予測できない未定義の結果が得られます。とにかく、setTimeoutの中でコードを実行していません。 –

+0

返された番号がclearTimeoutの一意のIDとして使用されているとします。 setTimeoutが一意のIDを返す理由。 – sabithpocker

+0

ああ、ありがとう。申し訳ありませんが、あなたを勘違いしました。このように実際に働いているようです。 –