JavaScriptのsetTimeout()でコールバック関数に引数を渡す

スポンサーリンク

JavaScript には sleep がないわけですが、特定の処理を遅らせたい場合、代わりに setTimeout() を利用します。昨晩この setTimeout() の書き方で手こずったので備忘録。

【お知らせ】 英単語を画像イメージで楽に暗記できる辞書サイトを作りました。英語学習中の方は、ぜひご利用ください!
画像付き英語辞書 Imagict | 英単語をイメージで暗記
【開発記録】
英単語を画像イメージで暗記できる英語辞書サービスを作って公開しました
スポンサーリンク

以下、mozilla の API リファレンスページ。

timeoutID = window.setTimeout(func, delay[, param1, param2, …]);
timeoutID = window.setTimeout(code, delay);

まず上手く動作しない例から

3秒後に alert を表示させるコードの例です。

第1引数にコードをそのまま渡しても、delay が効かず即座に alert 表示されてしまい、正しく動作しません。

setTimeout の第1引数にコードを渡す場合は、コードの文字列を渡す必要があるので、以下のようにしてみる。

これらも正しく動作しません。

正しく動作する例

greet + name がシングルクォートで囲まれるようにしないといけない。以下の書き方だと正常に動作します。

実際の動作確認は以下を参照、alert が表示されますのでご注意を。Runを押してみてください。
Edit fiddle – JSFiddle

このコード渡しの方法ですと、変数が2つ程度ならまだ良いけど、変数が多い場合で文字列と変数の連結が増えると、カオスで分けが分からなくなります。

コールバック関数の引数を setTimeout() の第3引数以降で指定

そこで、分かりやすい書き方として、setTimeout() の第1引数に無名関数のコールバックを渡す。コールバック関数に渡す引数は、setTimeout の第3引数以降で指定します。

こうすると、無名関数の中身 alert(a + b); の部分は、そのまま素のコードで書けるので分かりやすい。以下が参考になりました。

SCRAPBLOG : setTimeout のコールバック関数内でローカル変数を使用する

実際の動作確認は以下を参照、alert が表示されますのでご注意を。Runを押してみてください。
Edit fiddle – JSFiddle

ただしこの setTimeout() の第3引数以降にコールバックの引数を渡す書き方は、IEだと動かないらしい…。mozilla ページにあるIE用互換コードを使うか、以降の関数式を使う。

IE互換のためコールバックに関数式を使用する方法

以下のように、my_alert(a, b) 関数を定義して呼び出すようにする。

実際の動作確認は以下を参照、alert が表示されますのでご注意を。Runを押してみてください。
Edit fiddle – JSFiddle

IE互換を考えると、この書き方が無難でしょうかね…。ただし、「この方法は少し多くコストがかかります」と書いてありました。

clearTimeout でコールバックの動作をキャンセル

最後に、clearTimeout() 関数で setTimeout() のコールバックの動作をキャンセルする例です。マウスを動かすとコールバックの動作がキャンセルされるので、3秒経っても alert が表示されません。

実際の動作確認は以下を参照、alert が表示されますのでご注意を。
Edit fiddle – JSFiddle

Runを押してマウスを動かさない → 3秒後に alert 表示。
Runを押してマウスをすぐに動かす → alert がキャンセルされ3秒経っても表示されない。

という動作になるかと思います。

スポンサーリンク
オライリーのJavaScritp本(通称サイ本)は、昔かなり読み込みました。
 
スポンサーリンク
  • 4件のコメント
  • kt

    要はsetTimeoutの第1引数が関数オブジェクトであればいいので、関数を返す関数を利用するという方法もあります。

    greet = “hello”;
    name = “JS.”;

    function myAlert(text) {
    return function () {alert(text)};
    }

    setTimeout(myAlert(greet+name),3000);

    • taka

      kt さん、コメントありがとうございます。
      なるほどです。この書き方だと、setTimeout 呼び出し側がすっきり書けますね。
      参考になる情報をありがとうございました!

  • TOMO

    参考になりました。ありがとうございました。

    • taka

      TOMOさん、記事をお読み頂き&コメントありがとうございました!

Leave Your Message!