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

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

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

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

Q&A

解決済

2回答

899閲覧

js settimeout関数が期待どおりうごかない 

taishi1111

総合スコア5

JavaScript

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

0グッド

0クリップ

投稿2022/02/12 18:34

const okureru = (aisatu, zikann) => new Promise(resolve => setTimeout(resolve(aisatu), zikan)); okureru('konnnitiha', 5000).then(console.log)

.thenで5秒後にkonnnitihaがコンソールに表示される想定をしてましたが、、、、なぜか、実行後すぐに、コンソールにkonnnitihaと
表示されてしまいます。。。。

以前こちらのサイトに質問した際、
settimeout関数へのresolve関数を引数としての渡し方にミスがあり、

const okureru = (aisatu, zikan) => new Promise(resolve => setTimeout(()=>resolve(aisatu), zikan));

この書き方だと期待通り、動くことが判明しましたが、、、、

この意図しない動きについてですが、、、、
より詳細にドキュメントに載ってたりしますでしょうか、、、見つけられず、、、

今回の意図しない動きとしては、
setTimeout関数の仕様で、引数への値の渡し方に間違いがあったという認識でよろしいでしょうか、、、、

教えていただきたいです。

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

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

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

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

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

guest

回答2

0

ベストアンサー

今回の意図しない動きとしては、setTimeout関数の仕様で、引数への値の渡し方に間違いがあったという認識でよろしいでしょうか、、、、

一部には、はい。
イメージ説明
https://developer.mozilla.org/ja/docs/Web/API/setTimeout

まずsetTimeoutのつかいかたについての話をすると

setTimeout(console.log('konnnitiha'), 5000));

この書き方だと、第一引数に指定されたconsole.log('konnnitiha')がすぐ実行され、konnnitihaが表示されます。

そして console.log('konnnitiha') の戻り値 undefined がsetTimeoutに渡されるため、5秒後に表示されるものはありません。

(1つ前の質問に対するコメントでmaisumakunさんが書かれていますが、
setTimeoutに限らず、関数の実行前に、関数に指定した引数の方から先に評価(≒それが実行可能な形式であれば実行)されます。
setTimeout(console.log('konnnitiha'), 5000));
と書くと、setTimeoutという関数の実行前に、まず引数に指定した 「console.log('konnnitiha')」が評価されます。
console.log('konnnitiha') が評価されると、"コンソールに「konnnitiha」を出力する"という処理が実行され、undefinedが返ってきます。(console.log()関数の戻り値はundefinedです)
結果、 setTimeout(undefined , 5000));
として実行されるということです)


期待する動作(5秒後に"okureruを表示)をさせるには、第1引数に、「console.log('konnnitiha')という処理を実行する関数(関数オブジェクト)」を指定する必要があります。

js

1// console.log('konnnitiha')という処理を実行する関数 2function yobidashi() { 3 console.log('konnnitiha'); 4} 5// 関数オブジェクトを指定 6// ※「yobidashi()」のように括弧をつけると、setTimeoutの評価の前に 7// yobidashi関数が即時実行されundefinedが返ってくるため、期待する動作にならない。 8setTimeout(yobidashi, 5000);

 
これを無名関数を使って書き直すと

js

1setTimeout(function() {console.log('konnnitiha')}, 5000);

 
これをアロー関数式を使えば

js

1setTimeout(() => console.log('konnnitiha'), 5000);

となります。

こうすれば、「console.log('konnnitiha')を実行する関数」を5秒後に実行することになるので、意図する動作になります。

※「console.log('konnnitiha')」 も関数ではないかと思うかもしれませんが、これを引数に指定するとconsole.log()関数を実行することになってしまうため、関数の指定とは異なります。
もしあえてconsole.logを直接指定したいならば
setTimeout(console.log, 5000, 'konnnitiha');
となるでしょう。

ここらへんは「コールバック関数」のキーワードで検索するといろいろ解説が出てきます。
たとえば下記のページ等が参考になるでしょう。
https://qiita.com/matsuby/items/3f635943f25e520b7c20


あとは、querykumaさんの書かれているとおりです。
Promiseの引数関数も即時実行されます。

js

1const okureru = (aisatu, zikann) => new Promise(resolve => setTimeout(resolve(aisatu), zikan)); 2okureru('konnnitiha', 5000).then(console.log);

とすると、
Promiseオブジェクトの生成時、即時に setTimeout(console.log(aisatu), zikan)
が実行されますが、これは上述の通り、期待する動作となりません。

js

1const okureru = (aisatu, zikann) => new Promise(resolve => setTimeout(()=>resolve(aisatu), zikan)); 2okureru('konnnitiha', 5000).then(console.log);

とすると、
Promiseオブジェクトの生成時、即時に setTimeout(() => console.log(aisatu), zikan)
が実行されます。
そしてこれはsetTimeoutの引数に 「console.log('konnnitiha')を実行する関数)」を指定している為、期待する動作となります。


(※)Task Queへの登録等、Promiseの厳密な動作を考慮すると誤った言い回しがあるかもしれませんが、ここでは平易な理解のため詳細を割愛します。

投稿2022/02/13 00:42

編集2022/02/13 04:26
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

0

関数をどのタイミングで実行するかという関数の仕様です。

JavaScript

1var my_setTimeout = (my_function, time) => { 2 // time時間後にmy_functionを実行する 3 console.log(my_function, typeof my_function); // typeofで変数の型を調べる 4 if (typeof my_function === 'function') { 5 my_function(); // ()を付けることで関数を実行 6 } 7}; 8 9my_setTimeout(console.log(1), 1000); // my_function = undefined, typeof my_function = undefined 10 11my_setTimeout(()=>console.log(1), 1000); // my_function = ()=>console.log(1), typeof my_function = function

resolve(aisatu)と書くことで上のconsole.log(1)のほうになっています。

Qiitaに書いた記事ですがPromiseの引数関数は即時実行されます。
https://qiita.com/querykuma/items/651b5c3c7d0deda2e610

投稿2022/02/12 22:18

querykuma

総合スコア777

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問