.setInterval()

特定の時間間隔で、指定した関数またはコードの実行を繰り返し行います。 intervalIDを返します。

文法

//関数指定
var intervalID = window.setInterval(func, delay[, param1, param2, ...]);
//コード指定
var intervalID = window.setInterval(code, delay);

intervalIDは一意のインターバルIDで、 これはclearInterval()に渡すことが出来ます。

引数 説明
func (関数指定の場合)
繰り返し呼び出したい関数(function)を指定します。
code (コード指定の場合)
関数指定の代わりとなる文法で、繰り返し実行したいコード文字列を指定します。 (この構文の使用は、eval()の使用と同じ理由で推奨されません。)
delay setInterval()での各funcの呼び出し間隔を、ミリ秒(1/1000)単位の数値を指定します。 setTimeoutと同様に、 最小となる遅延時間が遵守されることになります。

1つ目の文法で関数へ引数(param1, param2)を渡すことは、 Internet Explorer 9とそれ以前のバージョンで動作しません。 もしこの機能を有効にしたいのであれば、互換性のあるコードを使用しなければいけません。 (詳細は、「コールバック引数」の段落を参照してください。)

注意: Gecko 13(Firefox 13.0 / Thunderbird 13.0 / SeaMonkey 2.10)より前のバージョンでは、 Geckoはミリ秒で"事実上の遅延"を示す追加引数をコールバックに渡していました。(翻訳に自信なし) この非標準の引数は、現在は提供されていません。

注意: 拡張機能の開発の範疇で、このメソッドを使用する場合は気をつける必要があります。 何故なら、拡張機能の更新のチェックのようなイベントの最中に、windowオブジェクトが更新され、 割り当てられているタイマーが失われるかもしれないからです。 (アドオン開発者フォーラムの例(英語)を参照) このような場合、 nsITimerインターフェースであれば、 より信頼性の高い結果を提供してくれます。

例1: 一般的な使用

var intervalID = window.setInterval(animate, 500);

例2: 2つの色を交互に入れ替え

下記の例は、あなたが「Stop」ボタンをクリックしてintervalIDをクリアするまで、 1秒に1回flashtext()を呼び出し続けます。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>setInterval/clearInterval example</title>
<script>
var nIntervId;

function changeColor() {
  nIntervId = setInterval(flashText, 500);
}

function flashText() {
  var oElem = document.getElementById("my_box");
  oElem.style.color = oElem.style.color == "red" ? "blue" : "red";
}

function stopTextColor() {
  clearInterval(nIntervId);
}
</script>
</head>

<body onload="changeColor();">
<div id="my_box">
<p>Hello World</p>
</div>
<button onclick="stopTextColor();">Stop</button>
</body>
</html>

例3: タイプライターのシミュレート

下記リンク先のデモは、指定したセレクタのグループにマッチしたNodeListの全てのテキストコンテンツを削除し、 setIntervalを使用することで、タイプライターをシミュレートしてテキストの打ち直しを行っています。 clearInterval()も参照してください。

JavaScript Typewriter - MDN Example

コールバック引数

コールバック関数に引数を渡す必要があり、 更に追加の引数(setTimeout()setInterval()のどちらも)が、 サポートされないInternet Explorer 9以下でも動作する必要がある場合、IE仕様に互換性のあるコードを含める必要があります。 下記のスクリプトは、単にスクリプトの先頭に挿入して、 両方のタイマーでそのブラウザでのHTML5の標準的な引数渡しの機能を有効にします。

/*\
|*|
|*|  JavaScriptのタイマーへのコールバック関数に
|*|  任意の引数を渡すことを有効にするIE用のPolyfillです。
|*|  (HTML5標準文法)
|*|
|*|  https://developer.mozilla.org/en-US/docs/Web/API/window.setInterval
|*|
|*|  文法:
|*|  var timeoutID = window.setTimeout(func, delay, [param1, param2, ...]);
|*|  var timeoutID = window.setTimeout(code, delay);
|*|  var intervalID = window.setInterval(func, delay[, param1, param2, ...]);
|*|  var intervalID = window.setInterval(code, delay);
|*|
\*/

if (document.all && !window.setTimeout.isPolyfill) {
  var __nativeST__ = window.setTimeout;
  window.setTimeout = function (vCallback, nDelay /*, argumentToPass1, argumentToPass2, etc. */) {
    var aArgs = Array.prototype.slice.call(arguments, 2);
    return __nativeST__(vCallback instanceof Function ? function () {
      vCallback.apply(null, aArgs);
    } : vCallback, nDelay);
  };
  window.setTimeout.isPolyfill = true;
}

if (document.all && !window.setInterval.isPolyfill) {
  var __nativeSI__ = window.setInterval;
  window.setInterval = function (vCallback, nDelay /*, argumentToPass1, argumentToPass2, etc. */) {
    var aArgs = Array.prototype.slice.call(arguments, 2);
    return __nativeSI__(vCallback instanceof Function ? function () {
      vCallback.apply(null, aArgs);
    } : vCallback, nDelay);
  };
  window.setInterval.isPolyfill = true;
}

setIntervalの別の使用方法に、コールバック関数の呼び出しに無名関数を使用する方法がありますが、 少し高価(訳注: 煩雑?)な方法です。例えば、下記のようなスクリプトになります。

var intervalID = setInterval(function() {myFunc("one", "two", "three");}, 1000);

また更に別の方法に、関数をbindする方法があります。

var intervalID = setInterval(function(arg1) {}.bind(undefined, 10), 1000);

非アクティブなタブについて

Gecko 5.0(Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2)からは、 非アクティブなタブ内では、インターバルの処理が1秒に1回以上実行されないように抑制されます。

thisの問題

setInterval()にメソッドを渡した場合(または、他の関数)、 異なるthis値で実行されます。 この事については、thisのページに詳細が説明されています。

解説

setInterval()によって実行されるコードは、 それが呼び出された関数とは別のコンテキスト内で実行されます。 そのため、呼び出された関数のthisキーワードには、 window(またはグローバル)オブジェクトが設定され、 setTimeoutを呼び出した関数のthis値とは異なります。 下記の例を参考にしてください。 (理解しやすいように、setInterval()の代わりにsetTimeout()を使用していますが、 どちらのタイマーにも関係する問題です。)

myArray = ["zero", "one", "two"];

myArray.myMethod = function (sProperty) {
    //引数があれば   this[sProperty] の値を
    //引数が無ければ this 値を出力
    alert(arguments.length > 0 ? this[sProperty] : this);
};

// "zero,one,two"を出力
myArray.myMethod();

// "one"を出力
myArray.myMethod(1);

// 1秒後に"[object Window]"を出力
setTimeout(myArray.myMethod, 1000);

// 1.5秒後に"undefined"を出力
setTimeout(myArray.myMethod, 1500, "1");



// 'this'オブジェクト渡しを試してみましょう。

// error: "NS_ERROR_XPC_BAD_OP_ON_WN_PROTO:
//Illegal operation on WrappedNative prototype object"
setTimeout.call(myArray, myArray.myMethod, 2000);
// 下記も同じエラーになります。
setTimeout.call(myArray, myArray.myMethod, 2500, 2);

ご覧の通り、コールバック関数へthisオブジェクトを渡すことは出来ません。

解決策

"this"問題の解決可能な方法は、2つのネイティブなグローバル関数である、 setTimeout()とsetInterval()を、 Function.prototype.callを通して、 this渡しが可能な非ネイティブな関数に置き換えることです。 下記はその置き換えの方法になります。

// JavaScriptのタイマー関数への'this'オブジェクト渡しを有効にします

var __nativeST__ = window.setTimeout, __nativeSI__ = window.setInterval;

window.setTimeout = function (vCallback, nDelay /*, argumentToPass1, argumentToPass2, etc. */) {
  var oThis = this, aArgs = Array.prototype.slice.call(arguments, 2);
  return __nativeST__(vCallback instanceof Function ? function () {
    vCallback.apply(oThis, aArgs);
  } : vCallback, nDelay);
};

window.setInterval = function (vCallback, nDelay /*, argumentToPass1, argumentToPass2, etc. */) {
  var oThis = this, aArgs = Array.prototype.slice.call(arguments, 2);
  return __nativeSI__(vCallback instanceof Function ? function () {
    vCallback.apply(oThis, aArgs);
  } : vCallback, nDelay);
};

注意: この2つの置換は、IEにおいてのHTML5標準のコールバック関数への任意の引数渡しも有効です。 そのため、標準に準拠しないPolyfillとして使用することが出来ます。 標準に準拠するPolyfillは、「コールバック引数」の段落を参照してください。

新しい機能の検証:

myArray = ["zero", "one", "two"];

myArray.myMethod = function (sProperty) {
    alert(arguments.length > 0 ? this[sProperty] : this);
};

// setTimeoutとsetIntervalの標準的な使用方法を保護しつつ…
setTimeout(alert, 1500, "Hello world!");

// 2秒後に、"zero,one,two"を出力
setTimeout.call(myArray, myArray.myMethod, 2000);

// 2.5秒後に"two"を出力
setTimeout.call(myArray, myArray.myMethod, 2500, 2);

このthis問題の、より複雑なもう1つの解決法は下記の小規模フレームワークになります。

注意: JavaScript 1.8.5では、Function.prototype.bind()メソッドが導入され、 このメソッドは与えられた関数内での、全ての呼び出しで使用されるthis値を開発者に指定させます。 これは、this値が呼び出される関数のコンテキストによって、 何になるのかはっきりしない問題を解決する手助けになってくれます。

小規模フレームワーク

時に、1ページ内に多数のアニメーションが使用されることがあります。 そのような状況で、全てのイベントの開始とその後にclearTimeout()を通して適切に停止する事は、 管理・保持するのが難しく、不自然な状態であると言えます。 この問題を解決するには、異なるオブジェクト内に各アニメーションの開始、停止等に必要とされる情報を全て入れ子にし、 それらのインスタンスを標準化しシンプルにするために、 オブジェクトのクラスのコンストラクタを作成します。 下記はそのような抽象クラスの条件を満たす最小限のサンプルであり、 こういった理由からMiniDaemonと名づけました。

注意: より複雑にはなりますが、この(デーモン)モジュールバージョンは、 Javascriptデーモン管理を参照してください。 このより複雑なバージョンは、Daemonコンストラクタのための大規模でスケーラブルなメソッドのコレクションに他なりません。 ただし、このDaemonコンストラクタ自体は、デーモンのインスタンス化中に、 initとonstart関数定義をサポートするために追加されたコードによるMiniDaemonのクローンに他なりません。 そのため、MiniDaemonフレームワークでは、 そのメソッドのコレクションを持たないDaemonは、基本的にはそのクローンであるため、 単純なアニメーションのために推奨される方法を残しています。

このコンストラクタの設計思想は、明示的にクロージャの使用を避けています。 また、コールバック関数へthisオブジェクトを渡す代わりの方法も提示します。 (詳細は「"thisの問題」を参照してください)

minidaemon.js

/*\
|*|
|*|  :: MiniDaemon ::
|*|
|*|  Revision #2 - September 26, 2014
|*|
|*|  https://developer.mozilla.org/en-US/docs/Web/API/window.setInterval
|*|  https://developer.mozilla.org/User:fusionchess
|*|
|*|  This framework is released under the GNU Lesser General Public License, version 3 or later.
|*|  http://www.gnu.org/licenses/lgpl-3.0.html
|*|
\*/

function MiniDaemon (oOwner, fTask, nRate, nLen) {
  if (!(this && this instanceof MiniDaemon)) { return; }
  if (arguments.length < 2) { throw new TypeError("MiniDaemon - not enough arguments"); }
  if (oOwner) { this.owner = oOwner; }
  this.task = fTask;
  if (isFinite(nRate) && nRate > 0) { this.rate = Math.floor(nRate); }
  if (nLen > 0) { this.length = Math.floor(nLen); }
}

MiniDaemon.prototype.owner = null;
MiniDaemon.prototype.task = null;
MiniDaemon.prototype.rate = 100;
MiniDaemon.prototype.length = Infinity;

  /* これらのプロパティは、読み取り専用であるべきです */

MiniDaemon.prototype.SESSION = -1;
MiniDaemon.prototype.INDEX = 0;
MiniDaemon.prototype.PAUSED = true;
MiniDaemon.prototype.BACKW = true;

  /* グローバルメソッド */

MiniDaemon.forceCall = function (oDmn) {
  oDmn.INDEX += oDmn.BACKW ? -1 : 1;
  if (oDmn.task.call(oDmn.owner, oDmn.INDEX, oDmn.length, oDmn.BACKW) === false || oDmn.isAtEnd()) { oDmn.pause(); return false; }
  return true;
};

  /* インスタンスメソッド */

MiniDaemon.prototype.isAtEnd = function () {
  return this.BACKW ? isFinite(this.length) && this.INDEX < 1 : this.INDEX + 1 > this.length;
};

MiniDaemon.prototype.synchronize = function () {
  if (this.PAUSED) { return; }
  clearInterval(this.SESSION);
  this.SESSION = setInterval(MiniDaemon.forceCall, this.rate, this);
};

MiniDaemon.prototype.pause = function () {
  clearInterval(this.SESSION);
  this.PAUSED = true;
};

MiniDaemon.prototype.start = function (bReverse) {
  var bBackw = Boolean(bReverse);
  if (this.BACKW === bBackw && (this.isAtEnd() || !this.PAUSED)) { return; }
  this.BACKW = bBackw;
  this.PAUSED = false;
  this.synchronize();
};

注意: この小規模フレームワークはコールバック関数への引数渡しを利用します。(このページの「コールバック引数」参照) もしネイティブでこの機能をサポートしないブラウザ上で動作させたい場合は、 ここで提示されたPolyfillを使用してください。

この小規模フレームワークの文法

var myDaemon = new MiniDaemon(thisObject, callback[, rate[, length]]);

アニメーションに必要とされる全ての情報が含まれたJavaScriptオブジェクトが返されます。 (thisのようなオブジェクト、コールバック関数、length、フレームレートが含まれる)

引数 説明
thisObject コールバック関数に呼び出されるthisオブジェクトを指定します。 object、またはnullを指定することが出来ます。
callback

繰り返し実行される関数を関数を指定します。 この関数の実行時には、下記の3つの引数が渡されます。

index
各実行での繰り返しのインデックス番号です。
length
デーモン(Daemon)に割り当てられた総実行数です。 有限または無限(Infinity)。
backwards
indexが増加しているか減少しているかを示す真偽値です。

これは、callback.call(thisObject, index, length, backwards)のようになります。 コールバック(callback)関数がfalse値を返すと、デーモンは停止します。

rate (任意)
各実行のインターバル時間(ミリ秒単位)を指定します。 デフォルト値は100です。
length (任意)
実行の総数を指定します。 これには正の数またはInfinityを指定可能で、 デフォルトはInfinityになります。
MiniDaemonのインスタンスプロパティ
引数 説明
myDaemon.owner 実行するデーモン(read/write)上でのthisオブジェクトです。 objectまたはnullを指定可能です。
myDaemon.task

繰り返し実行される関数です。(read/write) これは3つの引数で呼び出されます。

index
各実行での繰り返しのインデックス番号です。
length
デーモン(Daemon)に割り当てられた総実行数です。 有限または無限(Infinity)。
backwards
indexが増加しているか減少しているかを示す真偽値です。

前述した内容を参照してください。 myDaemon.task関数がfalse値を返すと、デーモンは停止します。

myDaemon.rate インターバル時間(ミリ秒単位)です。(read/write)
myDaemon.length 実行の総数です。 これは正の数またはInfinityになります。(read/write)
MiniDaemonインスタンスメソッド
引数 説明
myDaemon.isAtEnd() デーモンが開始/終了の位置にあるか否かの真偽値を返します。
myDaemon.synchronize() 実行時間に開始されたデーモンのタイマーを同期します。
myDaemon.pause() デーモンを停止します。
myDaemon.start([reverse]) デーモンを前進(各実行のindexを加算)、または後進(indexを減算)を開始します。
MiniDaemonグローバルオブジェクトメソッド
引数 説明
MiniDaemon.forceCall(minidaemon) 終端に到達したか否かに関わらず、実際のminidaemon.task関数への単一のコールバックを強制します。 いずれの場合も、内部のINDEXプロパティは加算/減算(実際の処理方向に依る)されます。

使用例

デモページを参照。

注意事項

setInterval()関数は、一般的にアニメーションのような次々に実行される関数に遅延(待機)設定を行うために使用されます。

この関数によるインターバルは、window.clearInterval()を使用してキャンセルします。

もし指定した遅延の後に一度だけ関数を実行したいのであれば、 window.setTimeout()を使用してください。

危険な使用方法

処理の実行時間がインターバル時間よりも長い可能性がある場合、 window.setTimeout()を使用して、 名前を付けた関数の再帰呼び出しを行うことをお勧めします。 例えば、setIntervalを使用して5秒毎にリモートサーバーにポーリングをしていて、 ネットワーク遅延、サーバが応答しない、またはホストの別の問題により、 リクエストが割り当てられた時間内に完了しないといったケースです。 そのため、必ずしもXHRリクエストが順番に返されて、キューに入れられていないという事に気づくでしょう。

このような場合、再帰setTimeoutパターンの使用が望ましいと言えます。

(function loop(){
   setTimeout(function(){

      // 処理をここに書きます。

      // 再帰呼び出し
      loop();

  }, 1000);
})();

上記のコードは、loopと名付けられた関数が宣言され、即座に実行されています。 処理の実行が完了した後に、setTimeout内部のloopが再帰的に呼び出されます。 このパターンは固定された(時間間隔での)インターバルを保証しませんが、 再帰の前に1つ前の実行が完了されていることは保証されます。

ブラウザ互換性

デスクトップ
機能 Chrome Firefox
(Gecko)
IE Opera Safari
基本 1.0 1.0 (1.7 or earlier) 4.0 4.0 1.0
callback(*1)
引数をサポート
10.0 ?
モバイル
機能 Android Chrome for
Android
Firefox
Mobile
IE
Mobile
Opera
Mobile
Safari
Mobile
基本 1.0 1.0 1.0 (1) 6.0 6.0 1.0
callback(*1)
引数をサポート
? ? ? ? ? ?

*1 関数を使用する文法で、任意の引数をサポートするか否かです。

仕様

DOMレベル0。標準の一部ではありません。

関連項目

 Back to top

© 2017 Mozilla Contributors
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.

このページは、ページトップのURL先のMozilla Developer Network(以下、MDN)のコンテンツを翻訳した内容を基に構成されています。 構成について異なる点も含まれますので、下記の項目を確認し、必要に応じて元のコンテンツをご確認ください。 もし、誤訳などの間違いを見つけましたら、 @tomofまで教えていただければ幸いです。

  • 特定のブラウザに特化しすぎている情報やあまりにも古い情報、 または試験的に導入されているようなAPIや機能については、省略していることがあります。
  • 例やデモについて、実際にページ内で動作させる関係で一部ソースコードを変更している場合や、 その例で使用しているコンテンツの単語や文章などを日本人向けに変更しいてる場合があります。
  • MDNの更新頻度が高いため、元のコンテンツと比べ情報が古くなっている可能性があります。
  • "訳注:"などの断わりを入れた上で、日本人向けの情報の追記を行っている事があります。