質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

3回答

759閲覧

【js】setIntervalから、prototypeで指定してる変数の値を取得する方法はないでしょうか?

hasshy

総合スコア102

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2018/11/10 13:02

以前、Deferredの半永久ループの件で質問させていただいたものです。

【jQuery】半永久的にチェーンメソッドでDeferredを連結し続ける方法

ご返答を元に、半永久(ユーザーの操作がない限り続く)ループを作って見たのですが、関数間のフラグの管理ができず困っています。

問題

関数の中で、this.isReadyというフラグを使いまわしたいのですが、
setIntervalの中では、undefindになってしまいフラグの値が取れないことがわかります。

どうすれば、setIntervarからもフラグを取得できるようになるのでしょうか?

コード

下記が実際のコードを質問用に加工したものです。

js

1function RandomComentSlider() { 2 3 this.isReady = 0; 4 this.intervalTimer; 5 6 // 順番に作業する。 7 this.commentDeferred = function() { 8 var md = new $.Deferred; 9 10 (() => { 11 // 省略 12 })().then( 13 // 省略 14 ).then( 15 // 省略 16 ).then(() => { 17 // 準備完了フラグを立てる 18 this.setIsReadyFlag(); 19 md.resolve(); 20 }); 21 22 return md.promise(); 23 } 24 25 // フラグを有効にするための関数 26 this.setIsReadyFlag() { 27 this.isReady = 1; 28 } 29 30 // 実行プロセス 31 this.run = function() { 32 console.log(this.isReady); // 0と正しく表示される 33 34 // 初回の一回は強制始動 35 this.commentDeferred() 36 37 // 1秒ごとに状態を監視 38 this.intervalTimer = setInterval(function(){ 39 console.log(this.isReady); // undifind 40 41 if(! this.isReady) return; 42 // もし準備が整ったら新しくイベントを実行 43 console.log('new comment') 44 this.commentDeferred(); 45 }, 1000); 46 } 47 48 // ループを止める 49 this.stopTimer = function(){ 50 clearInterval(this.intervalTimer) 51 } 52 53} 54 55// 起動処理 56var random = new RandomComentSlider(); 57random.run(); 58

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

はじめまして

setTimeout, setIntervalの引数に渡す関数では、通常thisがグローバルオブジェクト(ブラウザならwindow)になります。
そのため、問題のケースだとwindow.isReadyを取得しようとするため、設定されていなければundefinedとなります。
グローバル変数を設定するのは避けた方がよいので、別の方法を記します。

JavaScript

1// 省略 2this.run = function() { 3 // 省略 4 this.intervalTimer = setInterval(function(){ 5 console.log(this.isReady); // window.isReadyとなる 6 // 省略 7 }, 1000); 8} 9// 省略

JavaScriptには、関数のthisを指定(束縛)した関数を生成するFunction.prototype.bind()メソッドがあります。
このメソッドで生成した関数を、setTimeoutやsetIntervalに引数として渡せば、任意の値をthisとして関数内部で使用できます。

JavaScript

1// 省略 2this.run = function() { 3 // 省略 4 this.intervalTimer = setInterval((function(){ 5 console.log(this.isReady); // フラグの値 6 // 省略 7 }).bind(this /* 関数内で`this`として扱いたい値 */), 1000); 8} 9// 省略

解決策になれば幸いです。

参考資料

追記

他の方と入れ違いで回答したみたいなので、
回答の違いを説明しておきます。

kei344さんの回答は、アロー関数を使用したものです。
通常のfunctionのthisは「functionが実行された文脈に合わせて決定される」のに対して、
アロー関数のthisは「functionが記述された文脈に合わせて決定される」ことを利用して、
thisがwindowにならないようにしています。
アロー関数は対応ブラウザの問題もあるので、適宜調べてみてください。

投稿2018/11/10 13:51

編集2018/11/10 14:00
NozomuIkuta

総合スコア1260

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hasshy

2018/11/10 14:01

丁寧にご説明いただきありがとうございます! 現状のやり方だと、グローバル変数を見ていたのですね。 なるべく、有効範囲内(言い方があっていなければ申し訳ありませんが)の関数を使い回すためには、bindでthisに代入する方法があるのですね… 勉強になりました!
hasshy

2018/11/10 14:04

アロー関数の件もご回答いただきありがとうございます。 省略形というわけではないのですね… IEでは使えない(?)という話を伺っていたので、お伺いできて助かりました。
NozomuIkuta

2018/11/10 14:08

JavaScriptのthisはややこしいですよね。 bind()メソッド以外にもメソッドがあるので、Function.prototypeにどんなメソッドあるかについて調べると面白いかもしれません。 ではまた
NozomuIkuta

2018/11/11 06:37 編集

解決してたら、「解決済」の設定をお願いします。 質問一覧ページで区別がつかないので。 ついでに、別の方法も回答として記しておきます。 参考までに。
hasshy

2018/11/11 06:52

失礼しました。 回答済みにさせていただきました。 別方法についてもお教えいただきありがとうございます。
guest

0

function(){()=>{に書き換えてみては?

投稿2018/11/10 13:39

kei344

総合スコア69407

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hasshy

2018/11/10 13:57

ありがとうございます! 取得できました。 差し支えなければお聞きしたいのですが、無名関数の記述が統一されていなかった事が原因だったのでしょうか? 二つとも同じ意味だと思っていましたので、確かに揃っていないことは問題ですが、そこが原因だとは思い至りませんでした。
kei344

2018/11/10 14:07

違います。「JavaScript this」で調べてみてください。
hasshy

2018/11/10 14:17

アドバイスありがとうございます。
guest

0

解決してたら、「解決済」の設定をお願いします。

ついでに、別の方法です。
こっちの方が簡単かもしれません。

JavaScript

1// 省略 2this.run = function() { 3 var self = this; 4 // 省略 5 this.intervalTimer = setInterval(function() { 6 console.log(self.isReady); // フラグの値 7 // 省略 8 }, 1000); 9} 10// 省略

thisを変数にいれて、setIntervalに渡した関数の中で参照しています。
このやり方はクロージャを利用したものです。
興味があれば調べてみてください。

投稿2018/11/11 06:39

NozomuIkuta

総合スコア1260

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問