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

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

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

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

Q&A

解決済

3回答

232閲覧

settimoutがうまく動きません。どこに問題があってループしないのでしょうか?

退会済みユーザー

退会済みユーザー

総合スコア0

JavaScript

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

0グッド

0クリップ

投稿2018/03/01 11:21

settimoutがうまく動きません。どこに問題があってループしないのでしょうか?

https://teratail.com/questions/115616?whotofollow=
の続き

(function () { var item0 = document.getElementById('slide0'); var item1 = document.getElementById('slide1'); var item2 = document.getElementById('slide2'); var item3 = document.getElementById('slide3'); var arrayItem = [ item0, item1, item2, item3 ]; var i = 0; function loop() { arrayItem[i].classList.add('slide-fadeout'); arrayItem[i].classList.remove('slide-fadein'); ++i; if(i === arrayItem.length) { i = 0; } arrayItem[i].classList.add('slide-fadein'); arrayItem[i].classList.remove('slide-fadeout'); setTimeout(loop, 18000); }; })();

また、setintervalを使わずにsettimeoutを使って自分を読みだしてループさせると
setIntervalは、前に行ったタスクが削除されずに残ってしまうので、12345と処理のタスクが増えていって、ものすごく重くなる問題が解決するのでしょうか?

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

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

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

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

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

guest

回答3

0

setIntervalは、前に行ったタスクが削除されずに残ってしまうので、12345と処理のタスクが増えていって、ものすごく重くなる問題が解決するのでしょうか?

まぁ、setIntervalでもloop関数の中で呼ぶ構造になっていなければ大丈夫です。
その場合ループという名称はおかしいので、slideShowにでも変更した方が良いかもしれないですね

JavaScript

1(function () { 2 var item0 = document.getElementById('slide0'); 3 var item1 = document.getElementById('slide1'); 4 var item2 = document.getElementById('slide2'); 5 var item3 = document.getElementById('slide3'); 6 var arrayItem = [ 7 item0, 8 item1, 9 item2, 10 item3 11 ]; 12 var i = 0; 13 // JSは巻き上げを防ぐ為に普通の変数に無名関数を代入した方が良い 14 var slideShow = function () { 15 arrayItem[i].classList.add('slide-fadeout'); 16 arrayItem[i].classList.remove('slide-fadein'); 17 ++i; 18 // ここの条件式は一致ではなく以上にしたほうが良い 19 if(i => arrayItem.length) { 20 i = 0; 21 } 22 arrayItem[i].classList.add('slide-fadein'); 23 arrayItem[i].classList.remove('slide-fadeout'); 24 }; 25 setInterval(slideShow, 18000); 26})();

【おまけ】 前回の質問のおまけで書いた大規模リファクタリング

フルスクラッチでばばーと書いたので品質は微妙ですが、
構文エラーは出てない事は確認済みです。

JavaScript

1// DOMを触るので描画完了まで遅延させたほうが良い 2document.addEventListener("load", function () { 3 // 行数を減らす為にArray.prototype.mapを使って一気に宣言 4 var items = [0, 1, 2, 3].map(function(it){ 5 return document.getElementById('slide' + it); 6 }); 7 var fadeIn = function (i) { 8 items[i].classList.add('slide-fadein'); 9 items[i].classList.remove('slide-fadeout'); 10 } 11 var fadeOut = function (i) { 12 items[i].classList.add('slide-fadeout'); 13 items[i].classList.remove('slide-fadein'); 14 } 15 var slideShow = function (i) { 16 if (i => items.length) { 17 i = 0; 18 } 19 fadeIn(i); 20 fadeOut(i === 0 ? items.length - 1 : i - 1); 21 setTimeout(slideShow.bind(null, i + 1), 18000); 22 } 23 setTimeout(slideShow.bind(null, 1), 18000); 24});

投稿2018/03/01 11:55

miyabi-sun

総合スコア21158

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

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

root_jp

2018/03/01 12:32

JavaScriptの「巻き上げ」という現象知りませんでした。。。 調べてみましたが、これは起きてしまうと、この現象を知らないと原因が分かりませんね。 勉強になります。
miyabi-sun

2018/03/02 01:08

root_jpさんの回答にある(fn)()で即定義して逃げるやり方は、 関数宣言の構文ではなく、式の評価結果が関数という扱いになるので既存スコープに反映されません。 もちろん巻き上げも無しで、loop関数をスコープ上に残したくない時の優れた一つになりますね。
退会済みユーザー

退会済みユーザー

2018/03/02 04:15

ありがとうございます。おかげさまで解決しました。 >>> setIntervalでもloop関数の中で呼ぶ構造になっていなければ大丈夫です。 これはなぜ外だとタスクが増えていって、中だと増えないのでしょうか?
miyabi-sun

2018/03/02 04:18

> これはなぜ外だとタスクが増えていって、中だと増えないのでしょうか? 逆です逆。 よく読んで下さい 外なら1個のみ、中に配置すると無限に増えますよ。
退会済みユーザー

退会済みユーザー

2018/03/02 06:30

下記のように始めになっていたのですがもしかしてはじめから、これなら増えていかなかったのですか? function loop() { 処理 }; setInterval(loop, 17000);
guest

0

一発目のloop()が呼ばれてませんね。
loop()関数を即時実行してみてはどうでしょう。

JavaScript

1(function () { 2 var item0 = document.getElementById('slide0'); 3 var item1 = document.getElementById('slide1'); 4 var item2 = document.getElementById('slide2'); 5 var item3 = document.getElementById('slide3'); 6 var arrayItem = [ 7 item0, 8 item1, 9 item2, 10 item3 11 ]; 12 var i = 0; 13 (function loop() { 14 arrayItem[i].classList.add('slide-fadeout'); 15 arrayItem[i].classList.remove('slide-fadein'); 16 ++i; 17 if (i === arrayItem.length) { 18 i = 0; 19 } 20 arrayItem[i].classList.add('slide-fadein'); 21 arrayItem[i].classList.remove('slide-fadeout'); 22 setTimeout(loop, 18000); 23 }) (); 24}) ();

ものすごく重くなる問題が解決するのでしょうか?

解決します。
setTimeoutは登録した関数を1回だけ実行します。
1回しか実行しないため、繰り返し実行するためには、必要な分だけ再度登録する必要があります。
setIntervalは自分でストップしない限り、登録した関数を永久に実行し続けます。

追記

ちょっと語弊があるため追記します。
今の作りのままsetTimeoutをsetIntervalに変えてしまうと、毎回setIntervalに関数が登録され
永久に実行される関数が1個2個3個と増えていってしまうため、
ものすごく重くなりますよというのが言いたいことです。
setIntervalに1回だけ関数を登録するのであれば問題はありません。

見た感じ、永久に処理を続けたい感じなので、setIntervalの方が用途としては合ってそうですね。
ただし、setInterval用に作りを変える必要はあります。

投稿2018/03/01 11:36

編集2018/03/01 12:21
root_jp

総合スコア4666

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

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

退会済みユーザー

退会済みユーザー

2018/03/02 04:20

ありがとうございます。おかげさまで解決しました。 >>> 解決します。 setTimeoutは登録した関数を1回だけ実行します。 1回しか実行しないため、繰り返し実行するためには、必要な分だけ再度登録する必要があります。 setIntervalは自分でストップしない限り、登録した関数を永久に実行し続けます。 intervalは、第一引数に指定したloop関数を何個も実行してしまうので、loop関数が1つでループするのに同じ関数を12345と増やしていって重くなる仕様なのですね。 なんでこんな変な仕様なのかわかりませんが、基本的にtimeoutは一度しか関数を実行しないのでこちらで分を呼び出す方が良いのですね。 ループは常にこちらを使う方がよさそうですね。
root_jp

2018/03/02 04:53

おそらく、loop()関数の中でsetIntervalを呼んでいるからだと思います。 という指摘がされていますね。
guest

0

ベストアンサー

function loop(){}が一度も呼ばれていないので、関数loopの中で呼んでいるsetTimeoutが実行されないだけではないでしょうか?(動作未確認ですが)

投稿2018/03/01 11:34

HayatoKamono

総合スコア2415

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

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

退会済みユーザー

退会済みユーザー

2018/03/02 04:15

ありがとうございます。おかげさまで解決しました。 灯台下暗しでした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問