質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

2回答

394閲覧

for文内での変数の出力

aae_11

総合スコア178

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2019/08/14 14:12

以下のコードの最初のfor文の実行結果は「5」が5回出力される形となります。
何故、0から順に5まで出力されず「5」が5回出力されるのでしょうか?

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

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

何故、0から順に5まで出力されず「5」が5回出力されるのでしょうか?

  • JavaScriptはシングルスレッド動作なので、同時に複数コードを実行出来ません(Service Worker を除く)
  • シングルスレッドなので、実行完了するまで余所のコード実行を待機させます
  • シングルスレッドなので、同期コード/非同期コードはそれぞれ実行開始から実行完了まで連続処理されます(割込処理は働きません)

for 文は同期コードsetTimeout非同期コードなので、

  1. 先に実行された for の処理を完了まで実行する
  2. setTimeout のタイマー処理が働く

という処理順になります。

2つ目のfor文では何故、0~4までの数値を出力するのでしょうか...?

4つの変数か各々、独立したスコープを持っているからです。

Re: aae_11 さん

投稿2019/08/14 23:49

編集2019/08/15 03:41
think49

総合スコア18156

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

aae_11

2019/08/15 00:36

ご回答ありがとうございます。 for文は同期コードであり、setTimeoutは非同期コードであるということなのですが、2つ目のfor文では何故、0~4までの数値を出力するのでしょうか...?
think49

2019/08/15 03:42

親記事に追記しました。
aae_11

2019/08/15 04:17

追記ありがとうございます。 今の自分ではまだ、イメージが掴めないため、色々と調べ、理解が進みましたら、また参考にさせて頂ければと思います。
guest

0

ベストアンサー

FAQですね。

var変数の箱は1つだけでlet変数の箱はループブロックの数だけいっぱいあります。
最初のfor文はsetTimeoutの時間差後に1つのvar変数(ループ終了後に5になる)を出力しています。

コメントの回答

自分の認識では、varが0の時setitimeout関数が実行され、console.log(i)によって「0」が出力されると思うのですが、そうではないのでしょうか...?

setitimeout関数はdelayミリ秒の後にfunctionを実行するものです。

var timeoutID = scope.setTimeout(function[, delay]);

WindowOrWorkerGlobalScope.setTimeout() - Web API | MDN

setTimeout(function () { console.log(i); }, 1);

で1ミリ秒後(1秒の1/1000)にしていることが理解を妨げていると思います。

setTimeout(function () { console.log(i); }, 2000);

として2000ミリ秒後(2秒後)にしましょう。

varが0の時setitimeout関数が実行され、console.log(i)によって「0」が出力されると思うのですが、そうではないのでしょうか...?

コンピューターの計算は爆速ですから、2秒後にはfor文のvar i=0からi=4まで実行されて終わっています。

setitimeout関数は指定ミリ秒後にfunctionを実行するものです。

varが0の時setitimeout関数は実行しますfunctionの中身は実行しません
functionの中身を実行するのは指定ミリ秒後です。

指定ミリ秒後が2秒後とすれば、2秒後にはvar変数の値は5になっています。

しかし、そうなりますと疑問な点が生じてしまうのですが、何故、質問本文に記載させて頂きましたコードの2つ目のfor文(letを使用している方)の場合では、0から4が順に出力されることになるのでしょうか?

変数letはブロックスコープだからと思います。
変数letのときforループのループブロックごとに別の箱(メモリの場所)が用意されます。
同じ変数letでも別の箱を見ています。
変数にletを使うことでプログラムに不具合が起きにくくなるようです。

箱のイメージ

こちらは別の回答のために作成した図です。

varは1つの箱を使いまわしして、letは箱をいっぱい作ると理解しています。

投稿2019/08/14 14:26

編集2019/08/15 15:32
querykuma

総合スコア777

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

aae_11

2019/08/14 22:29 編集

ご回答ありがとうございます。 デベロッパーツールでも確認してみたのですが、いまいち変数の遷移が分からないといった状態です... 自分の認識では、varが0の時setitimeout関数が実行され、console.log(i)によって「0」が出力されると思うのですが、そうではないのでしょうか...?
querykuma

2019/08/15 08:16

親記事に追記しました。
think49

2019/08/15 09:44

> コンピューターの計算は爆速ですから、2秒後にはfor文のvar i=0からi=4まで実行されて終わっています。 JavaScriptはシングルスレッドなので、for文の処理が完了していなくても割込は発生しないと思います。
aae_11

2019/08/15 09:56

追記頂きありがとうございます。 大変分かりやすくご説明頂きましたおかげで、だんだんイメージが掴めてきました。 つまりは、1ミリ秒の間でfor文のループが5回実行されsettimeout関数も同じく5回実行されているが、functionの中身が実行されていないため、for文が終わった直後(varの値が5になった時)にfunctionの中身が実行されているため、console.log()には「5」が5回実行されていることになっているのでしょうか...? しかし、そうなりますと疑問な点が生じてしまうのですが、何故、質問本文に記載させて頂きましたコードの2つ目のfor文(letを使用している方)の場合では、0から4が順に出力されることになるのでしょうか? 重ね重ねお聞きしてしまって申し訳ないのですが、教えて頂けましたら幸いです...
querykuma

2019/08/15 15:32

親記事に追記しました。
aae_11

2019/08/16 01:59

何度もすみません。分かりやすくご説明頂きましたおかげで、大分理解することができました。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問