JavascriptのsetInterval, setTimeoutのコツ

Javascriptにおいて、一定時間後または一定時間ごとに関数を実行するには、

window.setInterval("呼び出す関数","待機時間");
window.setTimeout("呼び出す関数","時間間隔");

とする。

しかし、このsetIntervalとsetTimeout、呼び出す関数に引数を渡すときにちょっとめんどくさい。

というのも、

var timer;

function func1(){
    timer=window.setTimeout("func2('"+"こんにちは"+"')",1000);
}

function func2(str){
    window.alert(str);
}

などとしなければならない。

var timer;

function func1(){
    var message = "こんにちは";
    timer = window.setTimeout("func2('"+message+"')",1000);
}

function func2(str){
    window.alert(str);
}

こんな感じに、呼び出し元の関数func1のローカル変数もこの方法なら受け取ってくれる。

しかし、引数にHTML要素を送ろうとするとうまくいかない。例えば、

var timer;

function func1(){
    var arg=document.getElementById("box");
    window.alert(arg.innerHTML);
    timer=window.setTimeout("func2("+arg+")",1000);
}

function func2(arg){
    window.alert(arg.innerHTML);
}

この場合、func1から実行されたアラート(5行目)は確実に動くが、func2から実行されたアラート(10行目)はfirefoxではundifinedで返ってくる。(IEでは’object’は定義されていませんというエラー)

そこで、解決法として用意できるのが以下の例。

var timer;

function func1(){
    var arg=document.getElementById("box");
    window.alert(arg.innerHTML);
    var func2 = function(){
        window.alert(arg.innerHTML);
    };
    timer=window.setTimeout(func2,1000);
}

このようにfunc1のなかでfunc2を定義してやる。

func2はクロージャとなるのでエンクロージャのfunc1のローカル変数を参照できる。

つまり引数として受けとるのではなく、func1の変数をfunc2で扱うということ。

こうすることのメリットはもうひとつあって、setIntervalやsetTimeoutを解除するときに使うために宣言していたグローバル変数も、呼び出し元のローカル変数にしておける。例として…

function func1(){
    var arg=document.getElementById("box");
    arg.innerHTML="0";
    var i=0;
    var func2 = function(){
        arg.innerHTML=++i;
        if(i==10){
        	clearInterval(timer);
        }
    };
    var timer;
    timer=window.setInterval(func2,1000);
}

このように、func1のローカル変数timerにsetIntervalがしまわれていて、func2でclearIntervalするときにtimerを参照している。

さらに着目すべきはfunc2でカウントアップされていく変数iもfunc1のローカル変数であるところ。

クロージャfunc2からエンクロージャfunc1の変数を書き換えることもできるということ。

これを使いこなせばsetInterval, setTimeoutがだいぶ楽に書けそう。

おまけとして、クラスのメソッドでsetInterval, setTimeoutを使うときの方法。

function test(){
    var testes = new func("hoge");
    testes.timer();
}

function func(name){
    this.name=name;
}
func.prototype.timer = function(){
    setTimeout(this.alert,1000);
}
func.prototype.alert = function(){
    window.alert(this.name);
}

この場合、赤字部分のthisがうまく動かない。setInterval, setTimeoutから呼び出された場合のthisはwindowになるとか。

となると少しめんどくさいが、

function test(){
    var testes = new func("hoge");
    testes.timer();
}

function func(name){
    this.name=name;
}
func.prototype.timer = function(){
    var me = this;
    var alert = function(){
        window.alert(me.name);
    };
    setTimeout(alert,1000);
}

という感じでsetInterval, setTimeoutを呼び出し元の内側に盛り込んじゃえば、呼び出される関数alertがクロージャとなるので、エンクロージャtimerのローカル変数meにthisをごっそり入れてやると、関数alertでthisを間接的にだけど使うことができる。

広告

t87r について

趣味:トランペット・釣り・コーディング JavascriptとGAE/Pythonを勉強中。
カテゴリー: Web Design タグ: , パーマリンク

JavascriptのsetInterval, setTimeoutのコツ への1件のフィードバック

  1. ピンバック: setIntervalとsetTiemoutの関数に引数を使う方法 | cly7796.net

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中