[JS]setTimeoutでクラス関数を使いたい

このQ&Aのポイント
  • 特定のクラスの関数を実行する方法がわからない場合、setTimeoutを使用して待機してから実行することが一般的です。
  • グローバル変数を使用する場合、setTimeout内で関数を呼び出す方法がありますが、クラス関数を使用する場合には注意が必要です。
  • クラス関数を再呼び出す場合は、thisを使用してメソッドを参照することで解決することができます。
回答を見る
  • ベストアンサー

[JS]setTimeoutでクラス関数を使いたい

他の処理を待ってから、別の処理を実施したい場合に、setTimeoutを使用するのが 一般的だと思いますが、特定のクラスの関数を実行する方法がよくわかりません。 グローバル変数を使用する場合には以下で動きます。 ※待機の部分は、問題を簡略化するため今回は3回実行完了まで、としています。 counter = 0; max = 3; method(); function method(){ if ( counter < max ) { timerId = setTimeout(method, 10 ); console.log(counter); counter++; } else { console.log("done"); } } 出力は以下のとおり。 0 1 2 done methodやcounter, maxなどを隠蔽するため、クラス関数を作り、以下のようにしました。 a = new test(); a.method(); function test(){ this.counter = 0; this.max = 3; this.method = function(){ if ( this.counter < this.max ) { timerId = setTimeout(this.method, 10 ); console.log(this.counter); this.counter++; } else { console.log("done"); } } } 出力は以下のようになってしまい、意図したように実行できていません。 0 done このような場合、どのようにしてクラス関数を再呼び出しするのでしょうか。

質問者が選んだベストアンサー

  • ベストアンサー
  • askaaska
  • ベストアンサー率35% (1455/4149)
回答No.1

setTimeout関数は setTimeout呼出し後、他の処理に関係なく、指定した時間後に指定した関数を実行する よ 最初のコードが 0 1 2 done になる保証はないわ 何かの原因で console.log(counter); が遅延した場合 0 0 2 done なんていう風になる可能性もあるの それはおいといて setTimeout(this.method,10) で呼び出された2回目のfunction内では、 thisはページ全体を指してしまうので この記述だとif文のthis.counterがundefinedになって doneの方に飛んでしまうわね なので、関数内部ではthisで指定してはいけないわ 次のようにすればOK ・・・なはず(動作確認していないけど) まあ、setTimeoutスレッド問題はむししているけど function test(){ var o = this; o.counter = 0; o.max = 3; o.method = function(){ if ( o.counter < o.max ) { timerId = setTimeout(o.method, 10 ); console.log(this.counter); o.counter++; } else { console.log("done"); } } }

palayo
質問者

お礼

なるほど~。とても参考になりました!! setTimeoutは実際には一定間隔でループさせて 擬似的にwaitさせたいだけなので、 順番の維持とかは影響ないです。 ありがとうございました!!

その他の回答 (2)

  • fujillin
  • ベストアンサー率61% (1594/2576)
回答No.3

#2です。 ちょっと訂正。 if(--n>0)   ↓ if(n-->0) にしとかないとwaitが違ってしまうかも。

  • fujillin
  • ベストアンサー率61% (1594/2576)
回答No.2

methodの呼び出しはすでに回答がありますが、 >擬似的にwaitさせたいだけなので とのことですので、再呼び出しにこんな方法もあるかと… var delay = function(n, func){   (function(){     if(--n>0)       setTimeout(arguments.callee, 10);     else       if(func && typeof func==="function") func();   })(); } delay(300, function(){alert("hoge");}); delay(200, function(){console.log("done200");}); delay(100, function(){console.log("done100");}); // 結果は順に //done100 (console) //done200 (console) //hoge  (alert) delay(n, func)の nは繰り返し回数、 funcは経過後のコールバック

関連するQ&A

  • setTimeoutのthis参照について

    prototypeメソッドの中でsetTimeout関数を使用したところ、thisで自身の関数を参照しなくなりました。setTimeoutの挙動についてぐぐってみたのですが、いまいちsetTimeoutを使用したときのスムーズな記述方法がわかりません。 ******************************** var hoge=function(){ this.myName="ほげ"; } hoge.prototype={ init:function(){ setTimeout(function(){ hoge.prototype.displayName(); // ★(1)setTimeout関数の中でのメソッドの適した呼び出し方は? // ↑の記述でも呼び出せるけど、間違ってる気がする。。 },1000) }, displayName:function(){ // ★(2)ここでhogeオブジェクトのmyNameプロパティを参照するにはどう記述すれば良いのか? //console.log(this.myName); //↑setTimeoutを使ったのでthis参照はwindowオブジェクトになっているから違う //console.log(hoge.myName); →undefinedを返す } } window.onload=function(){ var a=new hoge(); a.init(); } ******************************** 上記のようなprototype関数を使用したときのスムーズな記述方法を教えていただけませんでしょうか。 知りたいのは下記2点です。 ★(1)prototypeメソッドを使用したとき、setTimeout関数の中でのメソッドの適した呼び出し方は? ★(2)setTimeout関数内で呼び出したメソッドから、自身のオブジェクトのプロパティを参照するにはどう記述すれば良いのか? 初心者なので説明が下手だったり、質問内容で間違った記述があるかもしれません。 質問内容で問題がありましたらご指摘いただけると助かります。

  • [JS] private関数からオブジェクト参照

    JavaScriptにて外部から使用する関数をpublicに、内部的に使用するだけの関数をprivateにしたく、 <http://d.hatena.ne.jp/brazil/20051028/1130468761>や<http://www.findxfine.com/programming/javascript/59.html>を参考に以下のようにしてみました。 func1はtestクラス内からしか呼び出せず、privateになっており、 func2はtestクラス外からも呼び出せて、publicになっているようです。 しかし、func2からfunc1を呼び出した際に、func2の呼び出しもとのオブジェクトを参照しようとすると undefinedになってしまいます。 var a = new test(); //a.func1(); // これはprivateなのでエラー a.func2(); // こちらはpublicなのでOK function test(){ var self = this; // private variable var data1 = 1; // public variable this.data2 = 2; // private function function func1(){ console.log(data1); // 1を表示 console.log(this.data2); // これがundefinedとなってしまう } // public function this.func2 = function(){ console.log(data1); // 1を表示 console.log(this.data2); // 2を表示 func1(); }; } どのようにすれば、オブジェクト変数を参照でき、 クラス内でのみ使用可能なprivate関数を定義できるのでしょうか。

  • setTimeoutあるいはsetIntervalの限界

    いつもお世話になっています。 タイマーの実験をしてみようかと思い、タイマー関数のサンプルをちょっと触ってみて、気になることがありました。 スクリプトとしては、次のようなものです。 <HTML> <HEAD> <SCRIPT Language="JavaScript"> <!-- timerID = 10; count = 0; function timerX(){ status = "Counter is " + count++; } function clr(){ clearInterval(timerID); } // --> </SCRIPT> <BODY bgColor="white" onLoad="timerID = setInterval('timerX()',1000);"> (以下略) このスクリプトを実行すると、1秒毎に1カウント増えていきますから、ステータスに表示される数値は10秒で10になります。 ですから、1を指定する、つまりsetInterval('timerX()',1);にすれば、論理上、10秒で10000になるはずですよね? ところが実際にステータスに出る数値はそうはならず、かなり低い数字になってしまいます。 そこで質問なのですが、setTimeoutまたはsetIntervalでタイマーを作る場合、ミリ秒はどのくらいまで有効なのでしょうか。 ひょっとして、マシンに依存するのでまちまちなのでしょうか。 経験等でご存じの方、お教えください。

  • 画像がフェードイン・アウトするクラスの作り方教えて..

    前置き:別に困っているわけでもありません ・こんな質問許されないかも(ご容赦を) ・自分で勉強しろと言われるかも(ごもっとも) ・ごみプログラムがさらにごみプログラムを生んでいるかも(ごめんなさい) 本題: いつぞやのタイトルくるくるのサンプルを基に、画像がフェードイン、 フェードアウトするオブジェクト指向っぽいスクリプトを作りました。 下のソースです。スタイル属性の変更をwindow.setIntervalを使って counter値に達するまでループ実行しているだけです。 似たような処理のfadeinクラスとfadeoutクラスを作って、  fadein.start(ターゲット,インターバルミリ秒);  fadeout.start(ターゲット,インターバルミリ秒); でフェードイン、フェードアウトを開始していますが、 fadeinクラスとfadeoutクラスをfadeinoutクラス一つにまとめちゃって、 fadeinoutクラスのメソッド(?)としてfadein、fadeoutを使えるように するには、どうやって作ればよいのかと言うのが質問です。 本当は、  var myobj = new fadeinout(ターゲット,インターバルミリ秒); とインスタンスして  myobj.fadein;  myobj.fadeout; みたく使うためのコーディングがよくわからんのです。 抜本的に書き換えた方がよいのでしょうか... <作ったサンプル> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="ja-JP"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta http-equiv="Content-Script-Type" content="text/javascript"> <title>FadeIn/FadeOut</title> <style type="text/css"></style> <script type="text/javascript" charset="utf-8"> <!-- var fadein = function (node,interval){ this.counter = 0; this.target = node; this.interval = interval; this.timerId = setInterval((function(that){ return function(){that.loop();}; })(this),this.interval); this.stop = function () { this.timerId && clearInterval(this.timerId); this.timerId = null; }; this.loop = function(){ this.target.style.width=this.counter+"px"; this.target.style.height=this.counter+"px"; this.target.style.opacity = this.counter / 100; this.target.style.filter = "alpha(opacity=" + this.counter + ")"; if( ++this.counter>100) this.stop(); }; }; var fadeout = function (node,interval){ this.counter = 100; this.target = node; this.interval = interval; this.timerId = setInterval((function(that){ return function(){that.loop();}; })(this),this.interval); this.stop = function () { this.timerId && clearInterval(this.timerId); this.timerId = null; }; this.loop = function(){ this.target.style.width=this.counter+"px"; this.target.style.height=this.counter+"px"; this.target.style.opacity = this.counter / 100; this.target.style.filter = "alpha(opacity=" + this.counter + ")"; if( --this.counter<0) this.stop(); }; }; fadein.start = function(target,interval){ new fadein(target,interval ); } fadeout.start = function(target,interval){ new fadeout(target,interval ); } function fadein_s(){ var target=document.getElementById("target"); fadein.start(target,1); } function fadeout_s(){ var target=document.getElementById("target"); fadeout.start(target,1); } // --> </script> </head> <body> <div> <image id="target" src="image/yahagi.png" style="width:0px;height:0px;"> </div> <button onclick="fadein_s();">フェードイン</button> <button onclick="fadeout_s();">フェードアウト</button> </body> </html>

  • クラスは関数の寄せ集め??

    クラスという概念がいまいちわかりません。 例えばMathクラスにはmax,sin,cos,tanなどの関数がありますが、 ようはクラスって関数(メソッド)を集めたものと思います。 そのような理解であっておりますでしょうか? であるならば、わざわざクラスに分類しなくても、関数(メソッド)で良い様に思うのです。 何でわざわざnew演算子を使ってオブジェクトを作成してからでないと 関数が使えないようにしたのか、さっぱりわかりません。 関数でいいじゃないですか。と思うのです。 「キミはsin()関数を作ってね、キミはcos()関数を作ってね。」 と 「キミはMathクラスのsinメソッドを作ってね、キミはMathクラスのcosメソッド作ってね」 では意味的にはたいして違わないと思うのです。 よろしくお願いします。

    • ベストアンサー
    • Java
  • JavaScript setTimeout

    失礼します現在ボタンがクリックされた場合、指定秒数をカウント後console.logし、再度ボタンがクリックされた場合秒数を初期化して、再度カウントするようにしたいのですがうまくいきません、何卒ご教授お願い致します。 <td align="center"><input type="button" value=" 1 " onclick="myValue(1)" style="width:100%; height:45px;"></td> <script type="text/javascript"> function hoge(){ //console.log("piyo"); } function myValue(myData){ setTimeout(hoge(),3000); } </script>

  • 実体化したクラスを関数の引数にするには

    タイトルの通りです。 実体化したクラスを関数の引数として渡し、 関数の中でクラスのメソッドを実行したいと思っています。 以下のソースではエラーが出るのですが、 お分かりの方はいらっしゃいますでしょうか? $o_hoge = new Class_hoge(); fncHoge = ($o_hoge); function fncHoge($class) {  $class->hoge('test'); } class Class_hoge {  public function hoge($a)  {   print $a;  } }

    • ベストアンサー
    • PHP
  • 関数の引数とグローバル変数について

    javascript初心者です。 どうしても分からないことがあるので質問させて頂きます。 グローバル変数の値を関数で処理して増やしコンソールログに表示していく、 というようなソースがあるとします。(以下) //グローバル変数 var a = 0; var b = 0; var c = 0; //計算する関数 var afunc = function(){   a++;   console.log(a); } var bfunc = function(){   b++;   console.log(b); } var cfunc = function(){   c++;   console.log(c); //onclickなどで呼び出す関数 function test1(){   var aplus = new afunc(); } function test2(){   var aplus = new bfunc(); } function test3(){   var aplus = new cfunc(); } グローバル変数や関数などが3つと数が少ないならこれでもいいかも知れませんが、 これが数十個とかに増えると、ソースの量もかなり多くなり 管理も大変になると思い簡略化させたいと考えました。 そこで以下のように変えてみたのですが、 加算がうまくいきません。 //グローバル変数 var a = 0; var b = 0; var c = 0; //計算する関数 vvar xxfunc = function(xx){   this.xx = xx;   this.show = function() {     this.xx++;     console.log(this.xx);   } } //onclickなどで呼び出す関数 function test1(){   var aplus = new xxfunc(a);   aplus.show(); } function test2(){   var aplus = new xxfunc(b);   aplus.show(); } function test3(){   var aplus = new xxfunc(c);   aplus.show(); } もしかすると、関数の引数にはグローバル変数を指定することができないのでしょうか? 何かうまいやり方はあるでしょうか? プログラミング自体が勉強し始めたばかりなので、 おかしなソースの書き方をしているかもしれませんのが、 ご教授、よろしくお願いいたします。

  • JSのクラスについての質問

    JSのクラスについての質問 ソース class Cat { constructor(name) {this.name = name} meow() {alert( this.name + 'はミャオと鳴きました' )} } //インスタンス作成 var clsObj = new Cat("my cat"); //インスタンス(オブジェクト)の中身を出力 console.log(clsObj); 初心者なのでこの中のどの記述が必須で、 またnameはどれと対になっているかがわかりません。 インスタンスはnew クラス名 となっている所で作成されて変数に作られたインスタンスが代入されるというのは何となく分かったのですが、 console.log(clsObj); VM793:9 Cat {name: "my cat"} となるのがいまいちわかりません。 new Cat("my cat");は class Cat { constructor(name) {this.name = name} meow() {alert( this.name + 'はミャオと鳴きました' )} } を実行するという事で、 引数は constructor(name) new Cat("my cat"); が対になっているのでnameがmycatに代わるという事でしょうか? new Cat("my cat");が実行された結果がインスタンスという事ですが、 mycatがインスタンスなのですか? 大変恐縮ですが、簡単に一連の流れを教えていただければ幸いです。 class Cat { constructor(name) {this.name = name} meow() {alert( this.name + 'はミャオと鳴きました' )} } にどう渡されてどのように処理され何がインスタンスとして吐き出されるのでしょうか?

  • ES6を学んでいるのですが難しいです。

    ES6を学んでいるのですが難しくて初心者にもわかるように解説していただけるとありたいです。 http://qiita.com/takeharu/items/cbbe017bbdd120015ca0 >>> 関数で複数の値を一度に返す一度に関数で複数の値を返すことができます。今まではオブジェクトや配列に代入して返していました。 function getFruit() { return ['りんご', 'バナナ'];} ES6 var [fruit1, fruit2] = getFruit(); ES5 console.log(fruit1); // りんごconsole.log(fruit2); // バナナ >>> 上記は function getFruit() { return ['りんご', 'バナナ'];} ES6 var [fruit1, fruit2] = getFruit(); ES5 ということだと思いますか? そのような説明がないのでわかりにくいですが、 ・ >>> 「...」演算子により、複数の値を一つの配列にまとめる「...」演算子を使用することにより、それ以降の値を一つの配列としてまとめることができます。 var [name, age, ...fruit] = ['ハル', 21, 'りんご', 'みかん']; console.log(name, age, fruit); // ハル 21 ['りんご', 'みかん'] また、「...」演算子を使用することにより、配列の展開もできます。 var array = [1, 2, 3]; console.log(array); // [1, 2, 3]console.log(...array); // 1 2 3 これにより今まで配列で最大値を求める場合は、applyメソッドを使用する必要がありました。しかし、展開することにより、簡潔に記述可能となります。 * Before var array = [1, 5, 3]; var max = Math.max.apply(null, array) console.log(max); // 5 * After var array = [1, 5, 3]; var max = Math.max(...array); console.log(max); // 5 >>> var max = Math.max(...array);の部分がおそらく新しいのだと思いますが、nullが...になっているというのは、 どういう意味で、どんなメリットがあるのでしょうか?

専門家に質問してみよう