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

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

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

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

Q&A

2回答

6254閲覧

JavaScriptのsetTimeoutを使った繰り返し処理について

rocksalt-gthb

総合スコア10

JavaScript

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

0グッド

1クリップ

投稿2017/05/27 08:42

###質問内容
下記のコードを実行して「10, 9, ...1, 0, 終了」というような結果を期待していたのですが,「10」の次に「終了」が出力されていました。
・なぜこのような結果になるのかよくわかりません。
・また期待していた結果を得る為にはどうすればよろしいでしょうか。
どなたかご教授よろしくお願いします。

###ソースコード

var count = 1000; var countdown = function(count){ console.log(count--); var tid = setTimeout(function(){ countdown(count); // 再起 }, 500); if (count < 0) { clearTimeout(tid); } }; countdown(10); console.log("終了");

###期待していた結果

10 9 8 7 6 5 4 3 2 1 0 終了

###実行結果

10 終了 9 8 7 6 5 4 3 2 1 0

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

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

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

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

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

guest

回答2

0

setTimeoutが「非同期」で動くからです。少し難しい部分もありますが、下記記事などを読んでみてはいかがでしょう。

【JavaScriptの同期、非同期、コールバック、プロミス辺りを整理してみる - Qiita】
http://qiita.com/YoshikiNakamura/items/732ded26c85a7f771a27

投稿2017/05/27 09:34

kei344

総合スコア69366

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

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

rocksalt-gthb

2017/05/28 07:52

ありがとうございます! 下記の記事を拝見しました。 私が書いたコードを実行すると,「console.log("終了");」の後に「countdown(count); // countの中身は9」がキューに登録されるという事ですね。
kei344

2017/05/28 07:55

そうですね。
guest

0

コードの挙動がわからないときは、ログ出力をしてみましょう。
たくさん出力しすぎるとかえって分かりにくくなるので注意が必要ですが。
JavaScript以外の言語でも、ログ出力ができるときは有効です。

JavaScript

1var countdown = function(count) { 2 console.log('countdown(' + count + ')開始!!'); 3 var argCount = count; // 引数countが変化するために保存 4 5 console.log(count--); 6 7 console.log('次にsetTimeout開始 count:' + count); 8 9 var tid = setTimeout(function(){ 10 countdown(count); // 再帰 11 }, 500); 12 13 console.log('setTimeoutからreturn!! tid: ' + tid + ' count:' + count); 14 15 if (count < 0) { 16 clearTimeout(tid); 17 console.log('clearTimeout(' + tid + ')からreturn!!'); 18 } 19 20 console.log('次にcountdown(' + argCount + ')からreturn'); 21}; 22countdown(10); 23console.log("終了");

ログ解析:

countdown(10)開始!!

10
次にsetTimeout開始 count:9
setTimeoutからreturn!! tid: 82 count:9
次にcountdown(10)からreturn
終了
undefined
countdown(9)開始!!
9
次にsetTimeout開始 count:8
setTimeoutからreturn!! tid: 83 count:8
次にcountdown(9)からreturn
countdown(8)開始!!
8
次にsetTimeout開始 count:7
setTimeoutからreturn!! tid: 84 count:7
次にcountdown(8)からreturn
countdown(7)開始!!

中略

countdown(1)開始!!
1
次にsetTimeout開始 count:0
setTimeoutからreturn!! tid: 91 count:0
次にcountdown(1)からreturn
countdown(0)開始!!
0
次にsetTimeout開始 count:-1
setTimeoutからreturn!! tid: 92 count:-1
clearTimeout(92)からreturn!!
次にcountdown(0)からreturn

再帰呼び出しによってcountdown(9)が開始される前に、
「setTimeoutからreturn」、「countdown(10)からreturn」していることがわかります。
そのために、「終了」がこのタイミングで表示されました。

期待していた結果を得る為には、同じようにログを見ると、
「clearTimeout(92)からreturn!!」の直後に
「console.log("終了");」を移動すればよいことがわかります。

よって、

JavaScript

1var countdown = function(count) { 2 console.log(count--); 3 var tid = setTimeout(function(){ 4 countdown(count); // 再帰 5 }, 500); 6 if (count < 0) { 7 clearTimeout(tid); 8 console.log("終了"); 9 } 10}; 11countdown(10);

ただし、コンソールによって、「10」の表示直後に、
countdown(10)の戻り値「undefined」が自動表示されることがあります。

投稿2017/05/27 13:38

naomi3

総合スコア1105

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

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

rocksalt-gthb

2017/05/28 07:45

ありがとうございます! 確かに,いつ呼び出されたり,returnされたりしているかが確認できますね。
naomi3

2017/05/28 08:19

最後のコードで「期待していた結果」になるのですが、何か質問はありますか?
rocksalt-gthb

2017/06/10 04:02

質問になるかわかりませんが,よくよく考えてみると,「期待していた結果」を得るためならば,下記の様に書けば,わざわざcountが-1の時にsetTimeout()を呼び出して,clearTimeout()を使って止めるという必要が無くすっきりとすると考えたのですが,いかがでしょうか。 var countdown = function(count){ if (count >= 0) { console.log(count--); var tid = setTimeout(function(){countdown(count);}, 500); } else { console.log("終了"); } }; countdown(10);
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問