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

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

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

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

Q&A

解決済

JavaScript forとsetTimeoutと配列を組み合わせた謎の挙動について

uyyuuyuyuy
uyyuuyuyuy

総合スコア7

JavaScript

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

2回答

0グッド

0クリップ

443閲覧

投稿2023/01/24 00:15

id="a"、b、cが最終的に全てleft:90%になるプログラムです
最終的に全てleft:90%になりません
原因がわからずにいます

setTimeoutを呼び出した時点でdocument.getElementById(i[n])のi[n]の中身は呼び出し時点の配列の中身で登録されていると思うのですが、違うんでしょうか

原因がわかる方教えてください

<script> window.onload=function(){ i=["a","b","c"]; x=["10","50","90"]; for(let n=0;n<i.length;n++){ for(let j=0;j<x.length;j++){ setTimeout(function(){ document.getElementById(i[n]).style.left=x[j]+"%"; },1000*Math.floor(Math.random()*5)); } } } </script> <div id="a" style="width:100px;height:100px;background:red;position:absolute;left:0%"> </div> <div id="b" style="width:100px;height:100px;background:green;position:absolute;left:0%"> </div> <div id="c" style="width:100px;height:100px;background:blue;position:absolute;left:0%"> </div>

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

dameo

2023/01/24 01:20 編集

多分0%→乱数時間空けて→10%→乱数時間空けて→50%→乱数時間空けて→90%としたいのでしょうけど、現状では 0%→乱数時間空けて→10% 0%→乱数時間空けて→50% 0%→乱数時間空けて→90% が平行で動いているため、最初の乱数時間よりも後ろ2つの乱数時間が短ければ先に90%や50%になってしまい、順番が狂ってしまいます。平行で動かさないためには、10%や50%にした「後」に「さらに待つ処理を入れ」ないawaitやPromiseを使わずに簡単に書くとこんな感じかと思います。 <script> window.onload = function() { i = ["a", "b", "c"]; x = ["0", "10", "50", "90"]; const f = function(i_idx, x_idx) { document.getElementById(i[i_idx]).style.left = x[x_idx] + "%"; if (++x_idx < x.length) { setTimeout(f, 1000 * Math.floor(Math.random() * 5), i_idx, x_idx); } } for(let n = 0; n < i.length; n++) { f(n, 0); } } </script> <div id="a" style="width:100px;height:100px;background:red;position:absolute;left:0%"> </div> <div id="b" style="width:100px;height:100px;background:green;position:absolute;left:0%"> </div> <div id="c" style="width:100px;height:100px;background:blue;position:absolute;left:0%"> </div>

回答2

1

こういうことでしょうか?

javascript

1window.addEventListener('DOMContentLoaded', async()=>{ 2 i=["a","b","c"]; 3 x=["10","50","90"]; 4 for(let n=0;n<i.length;n++){ 5 for(let j=0;j<x.length;j++){ 6 await new Promise(resolve=>{ 7 setTimeout(()=>{ 8 document.getElementById(i[n]).style.left=x[j]+"%"; 9 resolve(); 10 },100*Math.floor(Math.random()*5)); 11 }); 12 } 13 } 14});

投稿2023/01/24 00:37

yambejp

総合スコア109020

uyyuuyuyuy❤️を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

0

ベストアンサー

配列 x の各項目が順番に関係なく乱数秒後にleftプロパティにセットされるので、j2 のときの乱数が一番大きかったときだけ最終的に90%になります。setTimeout()は予約をするだけで即座に返ってくることがポイントです。

やりたいことがいまいちはっきりしませんが、「乱数 * 5 秒後に90%にしたい」ということでしょうか。

js

1for (let n = 0; n < i.length; n++) { 2 let finishDuration = 1000*Math.floor(Math.random() * 5); 3 for (let j = 0; j < x.length; j++) { 4 setTimeout(function(){ 5 document.getElementById(i[n]).style.left = x[j] + "%"; 6 }, finishDuration * (j + 1) / x.length); 7 } 8}

js

1 for (let n = 0; n < i.length; n++) { 2 let finishDuration = 1000 * Math.floor(Math.random() * 5); 3 document.getElementById(i[n]).animate( 4 [{left: '0%'}, {left: '90%'}], {duration:finishDuration, fill:'forwards'}); 5 }

「乱数 * 5 秒後に10%、その乱数 * 5 秒後に50%、その乱数 * 5 秒後に90%」であれば:

js

1for (let n = 0; n < i.length; n++) { 2 let duration = 0; 3 for (let j = 0; j < x.length; j++) { 4 duration += 1000 * Math.floor(Math.random() * 5); 5 setTimeout(function(){ 6 document.getElementById(i[n]).style.left = x[j] + "%"; 7 }, duration); 8 } 9}

3つの要素も(並列ではなく)順番に動かしたいなら:

js

1let duration = 0; 2for (let n = 0; n < i.length; n++) { 3 for (let j = 0; j < x.length; j++) { 4 duration += 1000 * Math.floor(Math.random() * 5); 5 setTimeout(function(){ 6 document.getElementById(i[n]).style.left = x[j] + "%"; 7 }, duration); 8 } 9}

投稿2023/01/24 00:26

編集2023/01/24 01:28
int32_t

総合スコア17125

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

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

ただいまの回答率
86.02%

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

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

質問する

関連した質問

同じタグがついた質問を見る

JavaScript

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