2017-11-28 10 views
0

私はJavaScriptを初めて使用しています。最近、コンソールに何が印刷されるのかという疑問を見つけました。正解は、参照渡しのために4 4 4 4です。しかし、私はこれがどのように結果であるのか分かりません。出力が単にiの値で、その値がfor-loopの反復のみに依存していると思われる場合、参照渡しが出力を指示するのはなぜですか?JavaScriptはこの動作をどのように説明していますか?

const array = [10, 21, 31, 41]; 

for(i = 0; i < array.length; i++) { 
    setTimeout(function print(array){ 
     console.log(i)}, 3000); 
} 
+0

参照渡しは関数の引数と関係があり、コード内にある唯一のものは使用されません。出力は参照渡しとは関係ありませんが、非同期コードとは関係ありません。 – trincot

答えて

2

ステップによってさて、ステップ:

const array = [10, 21, 31, 41]; 

for(i = 0; i < array.length; i++) { 
    setTimeout(function print(array) { /* stuff... */ }, 3000); 
} 

// When we get to here, the value of i is 4. 

このスニペットを実行すると、我々は、配列を反復し、反復ごとにタイムアウトを設定します。 forループが終了すると、setTimeoutが4回呼び出されましたが、setTimeoutに与えられた関数は実行されていません。実際、彼らはさらに3秒間走らないでしょう。

この時点で、最も重要なことに、iの値は4です。

三秒後...

は最後に、我々はsetTimeoutに与えた私達の機能printを実行しようとしています。だから、何をするか、その関数は、今iの値が今4であるので、それは4、4回を印刷し思い出す?:

function print(array) { console.log(i); } 

のように見えます。これは、関数が実際にを実行したときにであるため、関数が宣言されたときに、変数i,ではなく、の値が読み取られるためです。

基本的には、は、あなたの関数printが実際に呼び出された時点で4であり、従って4を驚くほど印刷します。

0

あなたのsetTimeoutは、wenn 3000のタイムアウトは、JavaScriptのループが前に終了してしまっていると、インデックスの最後の値はまた、「jsのイベントループ」とあなたのための番号4.検索を土気されますあなたのコードの非同期になりますブラウザが一言でどのように動作するかについて、さらに詳しく知ることができます。

1

タイムアウトによって呼び出されている内部関数をもう一度見てください。実際には、次のコードは、参照部でまったく同じこと(印刷4 4 4 4)

for(i = 0; i < array.length; i++) { 
    setTimeout(function print(){ 
     console.log(i)}, 3000); 
} 

パスを行いますがない時点で

function print(array){ 
    console.log(i); 
} 

実際には何のために使用される配列で渡され、つまり、print()関数に渡されるiの値ではなく、console.log(i)が呼び出されるときにiが保持する値の参照を意味します。 3秒の遅延があるので、ループには完了するのに十分な時間があり、最初のconsole.log(i)が呼び出されるまでにiの値は4になります。ループの後にiの値を設定することもでき、結果が変わります。

for(i = 0; i < 4; i++) { 
    setTimeout(function print(){ 
     console.log(i)}, 3000); 
} 

i = "foo"; 
// prints foo foo foo foo 
0

iの値は1つのみです。 setTimeoutを呼び出すと、元の値はどこにも格納されません。

forループの実行が終了した後にprint関数が呼び出されるため、iの値はforループの最後にあるため、4になります。

0

'i'値を使用できるようにするには、クロージャと呼ばれるものが必要です。その時点で関数が実行されると、iの値は4になり、印刷されます。