JavaScriptで処理を書いていると、ちょっと処理の開始を遅らせたりしたい時ってありますよね。
今日はそんな時に使えるメソッド、setTimeoutについて解説したいと思います。
下記の流れで、setTimeoutをバッチリ理解しちゃいましょう。
【基礎】setTimeoutとは?
【基礎】setTimeoutとsetIntervalの違い
【基礎】setTimeoutの使い方
【基礎】setTimeoutの活用例
【発展】setTimeoutの応用的な使い方
【発展】コールバック関数や引数を活用しよう
setTimeoutは、初心者の方にはなかなか理解しづらいメソッドの一つかもしれません。
この記事でしっかり覚えて、活用できるようになりましょう!
setTimeoutとは?
setTimeoutはある処理を一定時間後に実行するように命令することができるメソッドです。
JavaScriptの処理は、コードの上から順番に処理されていきますよね。
しかしその処理の速度は、私たちが感知できないほど一瞬で行なわれています。
それをちょっと待ってもらって、指定した時間後に実行するようにできるのがsetTimeoutです。
これを使うことで、Aの処理の5秒後にBの処理を行なう、ということもできるわけですね。
setTimeoutの使い方
では、setTimeoutの基本構文を見ていきましょう。
setTimeout(処理内容,実行タイミング)
setTimeoutは、第二引数に与えられた実行タイミング(ミリ秒)で、第一引数に定義された処理内容を1度実行します。
タイミングの単位がミリ秒なことに注意です。
つまり2秒の場合は2000、6秒の場合は6000と入力するわけですね。
setTimeoutの実用例
スライドを作ったり、サイトに素敵な動きをつけられるsetTimeout。
構文だけではなかなかイメージがつきづらいですね。
実際の使用例を見て、どのような動きになるのかを見ていきましょう。
読み込み完了してから3秒後にアラート表示
JavaScriptが読み込まれ、実行を開始してから3秒後にアラート表示される処理を実装してみましょう。
下記のように記述します。
var alertmsg = function(){ alert("3秒経過"); } setTimeout(alertmsg, 3000);
上記サンプルを実行するとalertmsg変数にセットされた関数(処理内容)が3秒遅れて実行されることが確認できます。
clearTimeoutでタイマーを停止する
タイマーは起動すると動きっぱなしのため、意図的に停止する方法について見ていきましょう!
タイマーを停止するには「clearTimeout()」メソッドを利用します。
このメソッドは引数にタイマーのIDを指定するのですが、実はsetTimeout()は返り値として固有のIDを取得することができます。
そこで、基本的な使い方としては次のようになります!
var id = setTimeout(関数, ミリ秒); clearTimeout(id);
この例では、setTimeout()の返り値を変数idに格納し、それをclearTimeout()の引数に設定していますね。
これにより、clearTimeout()が実行された時点でタイマーは停止します。
次の例を見てください!
var alertmsg = function(){ alert("3秒経過"); } var id = setTimeout(alertmsg, 3000); clearTimeout(id);
この例は前章で作成したタイマーのサンプルですが、一番最後にclearTimeout()を実行していますね。
つまり、3秒経過しても「alertmsg()」は実行されずに停止するわけです。
クリックしたら順番に表示
もっと具体的な例として、要素をクリックしたら5秒後にアラートが表示される処理を実装してみましょう。
このように、クリックイベントと組み合わせることも可能なのです。
setTimeoutの応用
この章では、setTimeout()をもっと深く理解するために、応用的な使い方を紹介していきます。
主に、タイマーの複数処理や動作しないパターン、0ミリ秒の設定について学習していきます。
複数のタイマー処理を実行する方法
setTimeout()によるタイマー処理は続けて複数のタイマーを起動させることができるので合わせてご紹介しておきます。
基本的な方法としては、setTimeout()の引数に指定した関数の中でさらに続けてsetTimeout()を実行するというものです。
次の例を見てください!
setTimeout(function() { console.log('1つ目のタイマー'); setTimeout(function() { console.log('2つ目のタイマー'); }, 1000); }, 2000);
実行結果
1つ目のタイマー 2つ目のタイマー
この例では、1つ目のsetTimeout()を実行した中でさらにもう1つのsetTimeout()を実行していますね。
このように関数内で連続して複数のsetTImeout()を実行することが可能で、1つずつ順番に指定された時間が経過する毎に処理が実行されていきます。
その証拠に、2つ目のタイマーは1つ目のタイマーよりも早く実行されるはずですが、実行結果を見ると順番に処理されているのが分かりますね。
このあたりは非同期処理との関連が大きいので、もしご興味のある方は次の記事で体系的にまとめているので参考にして見てください!
setTimeoutが動作しないパターン
setTimeout()の第1引数には関数を指定するわけですが、この指定方法をよく理解していないと上手くタイマーが動作しないことがあるのでご紹介しておきます。
まずは次の例を見てください!
function hello() { console.log('Hello'); } setTimeout(hello, 2000);
この例では、2秒後に指定した関数が実行されます。
この時に第1引数に指定した関数は「hello」ですよね?
しかし、これをうっかり「hello()」のように記述するパターンが多いのです。
( )を付与してしまうと関数は即時に実行されてしまうので、指定した時間が経過する前に関数は処理されてしまうわけです。
ただし、関数が引数を必要とする場合はどうすれば良いでしょうか?
次の例を見てください!
function hello(name) { console.log('Hello,' + name); } setTimeout(hello('Taro'), 2000);
この例では、関数が文字列を引数に受けとるのが分かりますが、上記のように記述すると期待した通りの動作はしません。
なぜなら、setTimeout()の第1引数に( )を付与すると即時に実行されてしまうからです。
実は、setTImeout()メソッドには第3引数が存在しており、ここに引数となる値を設定することができるのです!
function hello(name) { console.log('Hello,' + name); } setTimeout(hello, 2000, 'Taro');
この例では、setTimeout()の第3引数に設定した値を関数が受けとるようになるので、この場合は期待通りの動作になります。
setTimeoutに0ミリ秒を渡すとどうなる?
setTimeoutの第二引数は、処理を実行するまでの時間を指定できました。
ではその第二引数に0(ミリ秒)を与えると実行結果はどうなるか想像してみて下さい。
以下のサンプルコードと実行結果で確認しましょう。
var alertmsg2 = function(){ alert("2つ目のアラート表示"); } alert("1つ目のアラート表示"); setTimeout(alertmsg2, 0); alert("3つ目のアラート表示");
実行結果
//"1つ目のアラート表示" //"3つ目のアラート表示" //"2つ目のアラート表示"
以上のように、先に7行目のalert処理が実行され、setTimeoutに0秒を指定したdoLog2()が一番最後に実行されています。
0ミリ秒と指定されたsetTimeoutはすぐに実行されるように思いますが、先にメインの実行処理が行なわれるのです。
これはJavaScriptのルールによるものです。
この特性を利用して、ある負荷の高いメイン処理がちょうど終わった時に他の補足的な処理が実行されるようsetTimeoutに0を渡して実行する、という利用方法もありますので覚えておくと良いでしょう。
コールバック関数や引数を活用しよう
setTimeoutには、第一引数に関数や、無名関数などのコールバック関数を与えることができます。
また、誤ったコールバック関数の渡し方をしてしまうと、setTimeoutがうまく動きません。
しっかり確認して、活用できるようになりましょう!
コールバック関数への引数の渡しかた
setTimeoutのコールバック関数には、引数を与えることができます。
引数の渡しかたについての詳細は、以下の記事が解説してくれています。
ぜひ併せて読んでみてください。
thisを使って関数自身を指定しよう
通常、関数内のthisは関数自身を指していてます。
しかし、入れ子の関数(関数内の関数)ではthisはグローバル領域を指します。
このため、thisを安易に使うとその挙動が分からなくなってしまいますね。
しかし、回避策もあります。
以下のサンプルコードで見てみましょう。
window.onload = function () { // コールバック関数とその引数、thisなど // thisの使いかた function sampleClass() { this.name = sample; } // thisがグローバルになる例 sampleClass.prototype.method1 = function () { function logThis() { console.log('this1 = ' + this.toString()); } logThis(); } // thisがローカルになる例(回避策) sampleClass.prototype.method2 = function () { var keepThis = this; function logThis2() { console.log('this2 = ' + keepThis.toString()); } logThis2(); } var sample = new sampleClass(); sample.method1(); sample.method2(); }
実行結果
this1 = [object Window] //Windowsはグローバルエリアのオブジェクト this2 = [object Object] //Objectとは、sampleClass()のインスタンスのこと
以上のように、クラスにメソッドを追加する際に関数を入れ子にさせました。
一番目の例はthisをそのまま使っています。
その結果、入れ子内の関数ではthisはグローバルエリアのWindowsオブジェクトを指しています。これは仕様です。
回避策ではthisを一旦keepThis変数に保存し、入れ子内の関数でkeepThisを使用しています。
この場合のkeepThisは、入れ子関数内でもsampleClassのインスタンスであるObjectを指しています。
このように、仕様によりthisの挙動が変わってしまうのです。
問題がある場合は、回避策を使用してください。
thisの使い方は下記の記事で詳しく解説しているので、ぜひ確認してください。
setTimeoutとsetIntervalの違い
JavaScriptでは、setTimeoutに似たメソッドでsetIntervalがあります。
基本的に両方ともタイマー処理と呼ばれる時間に関連したメソッドですが、処理の流れが違います。
setTimeoutは一定時間が経過した後に処理が実行されます。
しかし、setIntervalは指定した時間ごとに処理を繰り返す処理になるのです。
次のサンプル例を見てください!
function hello(name) { console.log('Hello'); } var id = setInterval(hello, 1000);
この例では、setIntervalの引数に関数とミリ秒を指定しています。
このプログラムを実行すると1秒毎に関数「hello」が繰り返し実行されるわけです。
そのため、clearInterval()を利用してタイマーの動作を停止する処理も合わせて記述することになります。
このsetIntervalについて詳しく知りたい方は、下記の記事で体系的にまとめているのでぜひ参考にして見てください!
まとめ
いかがでしたか?
setTimeoutを使えば、処理の幅が広がりそうですね!
しかもJavaScriptでよく使われるため、覚えておいて損はない関数です。
JavaScriptのsetTimeoutについて忘れてしまったら、またこの記事をご覧ください!